* configure.ac: Add -Wmissing-prototypes flag to gcc.
* TODO: Updated.
Sat Dec 27 22:17:52 2003 Ben Pfaff <blp@gnu.org>
Dictionary classes: each variable is "ordinary", "system", or
"scratch".
* var.h: (enum dict_class) New enum.
* vars-prs.c: (dict_class_from_id) New function.
(dict_class_to_name) New function.
Sat Dec 27 22:16:06 2003 Ben Pfaff <blp@gnu.org>
* var.h: (struct freq_tab_set) Removed (not used).
Sat Dec 27 22:15:21 2003 Ben Pfaff <blp@gnu.org>
* value-labels.c: (val_labs_destroy) vls needs to be freed too.
Sat Dec 27 22:10:49 2003 Ben Pfaff <blp@gnu.org>
* stats.c: (hypercube) Rename pow4(). All references updated.
Sat Dec 27 22:05:49 2003 Ben Pfaff <blp@gnu.org>
* rename-vars.c: (cmd_rename_variables) Rewritten.
(compare_name) Removed.
Sat Dec 27 22:03:51 2003 Ben Pfaff <blp@gnu.org>
var_set feature, and code taking advantage of it.
* crosstabs.q: (static var var_dict) Removed.
(static var variables) New variable.
(static var variables_cnt) New variable.
(cmd_crosstabs) Free variables instead of var_dict.
(internal_cmd_crosstabs) Initialize and use variables,
variables_cnt instead of var_dict.
(free_var_dict) Removed.
(crs_custom_tables) Use var_set instead of a copied dictionary.
(crs_custom_variables) Set up variables, variables_cnt instead of
var_dict.
[DEBUGGING] (debug_print) Ditto.
* means.q: (mns_custom_tables) Use var_set instead of a copied
dictionary.
* vars-prs.c: (parse_vs_variable) New function.
(parse_dict_variable) Rewritten.
(parse_variable) Rewritten.
(parse_variables) Renamed parse_var_set_vars(), rewritten.
(parse_variables) New function in terms of parse_var_set_vars().
Now requires its first argument to be non-null. All references
that passed a null pointer updated to pass default_dict instead.
(macro id_dict) Removed.
(parse_DATA_LIST_vars) Add assertions.
(parse_mixed_vars) Ditto.
(struct var_set) New structure.
(var_set_get_cnt) New function.
(var_set_get_var) New function.
(var_set_lookup_var) New function.
(var_set_destroy) New function.
(dict_var_set_get_cnt) New function.
(dict_var_set_get_var) New function.
(dict_var_set_lookup_var) New function.
(dict_var_set_destroy) New function.
(var_set_create_from_dict) New function.
(struct array_var_set) New structure.
(array_var_set_get_cnt) New function.
(array_var_set_get_var) New function.
(array_var_set_lookup_var) New function.
(array_var_set_destroy) New function.
(var_set_create_from_array) New function.
* q2c.c: (dump_parser) Use parse_variables(default_dict, ...)
instead of parse_variables(NULL, ...) in output code.
Sat Dec 27 21:38:53 2003 Ben Pfaff <blp@gnu.org>
Change inp_init from a 2-bit vector to an ordinary array.
Initialize it all in cmd_end_input_program() instead of in
create_variable().
* inpt-pgm.c: (enum value_init_type) New enum.
(global var inp_init) Change to `enum value_init_type *', make
static.
(inp_init_size) Removed.
(inp_nval) Change to `size_t', make static.
(cmd_input_program) Don't initialize inp_init or inp_init_size.
(cmd_end_input_program) Initialize inp_init, inp_nval.
(init_case) Rewrite.
(clear_case) Rewrite.
* inpt-pgm.h: Removed.
Sat Dec 27 21:36:38 2003 Ben Pfaff <blp@gnu.org>
* hash.c: (hsh_hash_bytes) Use Fowler-Noll-Vo hash instead of
Colin Plumb hash. It is simpler and should better resist
collisions.
(hsh_hash_string) Ditto.
Sat Dec 27 21:34:57 2003 Ben Pfaff <blp@gnu.org>
* get.c: (export_write_case_func) Remove debug printing code.
Sat Dec 27 21:11:09 2003 Ben Pfaff <blp@gnu.org>
* get.c: (cmd_save_internal) Rename parameter. Use &t->h instead
of cast.
(save_write_case_func) Use &trns->h instead of cast.
(cmd_export) Use &t->h instead of cast.
Sat Dec 27 20:57:42 2003 Ben Pfaff <blp@gnu.org>
Moved vectors into the dictionary.
* var.h: (struct vector) Moved here from vector.h. `index' member
renamed `idx', `v' renamed `var', `nv' renamed `cnt'. All
references updated.
* vector.h: Removed.
* vector.c: (global var vec) Removed.
(global var nvec) Removed.
(cmd_vector) Rewritten.
(find_vector) Removed.
* dictionary.c: (dict_create_vector) New function.
(dict_get_vector) New function, replaces reading global vec[]
array.
(dict_get_vector_cnt) New function, replaces reading global nvec
variable.
(dict_lookup_vector) New function, replaces find_vector().
(dict_clear_vectors) New function.
Sat Dec 27 20:54:01 2003 Ben Pfaff <blp@gnu.org>
Start to move away from `struct variable' p `union' member to void
* aux member.
* var.h: (struct variable) Add `aux' member.
Sat Dec 27 20:36:25 2003 Ben Pfaff <blp@gnu.org>
Get rid of struct variable `foo' member.
* frequencies.q: (internal_cmd_frequencies) Use p.frq.used instead
of foo.
(frq_custom_variables) Ditto.
(frq_custom_grouped) Ditto.
* get.c: (struct save_trns) Change `var' member from `int *' to
`struct variable **'.
(cmd_save_internal) Use aux instead of foo.
(save_trns_proc) Use revised `var' member.
(static var mtf_seq_no) Renamed mtf_seq_num.
(static var mtf_seq_nums) New static var.
(cmd_match_files) Initialize mtf_seq_nums.
(mtf_free) Free mtf_seq_nums.
(mtf_processing) Use mtf_seq_nums instead of foo.
(mtf_merge_dictionary) No need to initialize mv->foo.
(cmd_export) Use aux instead of foo. Use revised `var' member.
(mns_custom_tables) Don't use foo to check for duplicates, that's
what PV_NO_DUPLICATE is for.
* var.h: (struct variable) Remove `foo' member.
(struct frequencies_proc) New member.
Sat Dec 27 19:46:13 2003 Ben Pfaff <blp@gnu.org>
Clean up COMPUTE and IF.
* compute.c: More or less rewrite the darn thing.
(struct compute_trns) Rename and reorder and add and delete
members.
(cmd_compute) Rewrite.
(compute_num) Make conditional on test expression. Now used for
both COMPUTE and IF.
(compute_num_vec) Ditto.
(compute_str) Ditto.
(compute_str_vec) Ditto.
(cmd_if) Rewrite.
(if_num) Removed.
(if_num_vec) Removed.
(if_str) Removed.
(if_str_vec) Removed.
(parse_target_expression) Renamed parse_rvalue_expression(),
rewritten.
(new_trns) Renamed compute_trns_create(), rewritten.
(delete_trns) Removed.
(free_trns) Renamed compute_trns_free(), rewritten.
(struct lvalue) New structure.
(parse_var_or_vec) Renamed lvalue_parse(), rewritten.
(lvalue_get_type) New function.
(lvalue_is_vector) New function.
(lvalue_finalize) New function.
(lvalue_destroy) New function.
Sat Dec 27 19:44:14 2003 Ben Pfaff <blp@gnu.org>
* command.def: Disallow MODIFY VARS in input mode, so that
variables can't get dropped and confuse cmd_end_input_program()'s
attempt to fill inp_init[].
* modify-vars.c: (static var forward_positional_ordering) New
variable.
(struct var_modification) Entirely changed.
(rearrange_dict) Interface changed, rewritten.
(cmd_modify_vars) Deal with modified struct var_modification, much
rewritten.
(struct var_renaming) New structure.
(compare_var_renaming_by_new_name) New function.
(validate_var_modification) New function.
* var.h: (struct modify_vars_proc) Removed.
(struct variable) Removed member p.mfv.
Sat Dec 27 19:40:26 2003 Ben Pfaff <blp@gnu.org>
Make EVALUATE a valid command whether we're debugging or not, so
that `make check' can succeed regardless of whether debugging is
turned on.
* command.def: [GLOBAL_DEBUGGING] Drop the #if.
* compute.c: [GLOBAL_DEBUGGING] (cmd_evaluate) Drop the #if.
Sat Dec 27 19:34:40 2003 Ben Pfaff <blp@gnu.org>
* apply-dict.c: (cmd_apply_dictionary) Replace a ghastly switch
statement by a simple if test.
* dfm.c: (dfm_get_record) Add assertion.
Sat Dec 27 17:51:26 2003 Ben Pfaff <blp@gnu.org>
For each file x.c, move #include "x.h" to the very top of the
include list, to catch x.h failing to include the proper headers.
Sat Dec 27 17:50:19 2003 Ben Pfaff <blp@gnu.org>
* algorithm.c: (find) New function.
(remove_equal) New function.
(set_difference) New function.
(adjacent_find_equal) New function.
[TEST_UNIQUE] Removed test case.
(copy_if) Find end test.
Sat Dec 27 17:42:45 2003 Ben Pfaff <blp@gnu.org>
* dictionary.c: (dict_get_case_weight) New convenience function.
* aggregate.c: (accumulate_aggregate_info) Use
dict_get_case_weight().
* frequencies.q: (calc_general) Ditto.
(calc_integer) Ditto.
(calc) Ditto.
* t-test.q: (groups_calc) Ditto.
(z_calc) Ditto.
Sat Dec 27 17:29:45 2003 Ben Pfaff <blp@gnu.org>
* glob.c: (global var default_dict) Change from `struct
dictionary' to `struct dictionary *'. All references changed.
(init_glob) Initialize default_dict with dict_create().
Sat Dec 27 17:06:06 2003 Ben Pfaff <blp@gnu.org>
struct dictionary now made opaque. All related functions:
* get.c: (rename_variables) Removed.
(dict_delete_run) Removed.
* temporary.c: (copy_variable) Removed.
(new_dictionary) Removed.
(save_dictionary) Removed.
(restore_dictionary) Removed.
(free_dictionary) Removed.
* vars-atr.c: (clear_default_dict) Removed.
(find_variable) Removed.
(find_dict_variable) Removed.
(create_variable) Removed.
(delete_variable) Removed.
(common_init_stuff) Removed.
(init_variable) Removed. Updating of inp_init moved into
cmd_end_input_program().
(replace_variable) Removed.
(rename_variable) Removed.
(clear_variable) Removed.
(dup_variable) Removed.
* vars-prs.c: (is_varname) Removed.
(is_dict_varname) Removed.
(fill_all_vars) Removed.
* vector.c: (find_vector) Removed.
* weight.c: (stop_weighting) Removed.
* dictionary.c: New file.
(dict_create) New, replaces new_dictionary().
(dict_clone) New, replaces save_dictionary() and
restore_dictionary().
(dict_clear) New, replaces clear_default_dict().
(dict_destroy) New, replaces free_dictionary().
(dict_get_var_cnt) New function, replaces references to
dict->nvar.
(dict_get_var) New function, replaces references to dict->var[i].
(dict_get_vars) New function, replaces fill_all_vars().
(dict_create_var) New, replaces create_variable(). Interface
drops `type' parameter, using a zero `width' to designate numeric.
(dict_clone_var) New, replaces dup_variable().
(dict_rename_var) New, replaces rename_variable().
(dict_lookup_var) New, replaces find_variable(),
find_dict_variable(), is_varname().
(dict_contains_var) New function.
(compare_variable_dblptrs) New function.
(dict_delete_var) New function, replaces clear_variable().
(dict_delete_vars) New function, replaces dict_delete_run().
(dict_reorder_vars) New function.
(dict_rename_vars) New function, replaces rename_variables().
(dict_get_weight) New function, replaces reading dict->weight_var.
(dict_set_weight) New function, replaces writing dict->weight_var
or calling stop_weight(dict).
(dict_get_filter) New function, replaces reading dict->filter_var.
(dict_set_filter) New function, replaces writing dict->filter_var.
(dict_get_case_limit) New function, replaces reading dict->N.
(dict_set_case_limit) New function, replaces writing dict->N.
(dict_get_value_cnt) New function, replaces reading dict->nval.
(dict_compact_values) New function, replaces a loop that was
replicated in several places.
(dict_get_split_vars) New function, replaces reading dict->splits.
(dict_get_split_cnt) New function, replaces reading
dict->n_splits.
(dict_set_split_vars) New function, replaces writing dict->splits.
(dict_get_label) New function, replaces reading dict->label.
(dict_set_label) New function, replaces writing dict->label.
(dict_get_documents) New function, replaces reading
dict->documents.
(dict_set_documents) New function, replaces writing
dict->documents.
All references to above functions updated.
* aggregate.c: (cmd_aggregate) Copy file label and documents from
old dictionary to new by hand, because dict_create() can't do it
itself. Use dict_set_documents(), dict_set_split_vars().
* temporary.c: (cancel_temporary) Also set temp_dict to NULL after
calling dict_destroy().
* data-list.c: (dls_var_spec) Remove `type' member, replace by
`width'.
(fixed_parse_compatible) Some slightly nontrivial changes for
dict_create_var().
(dump_fmt_list) Ditto.
(parse_free) Ditto.
* file-type.c: (create_col_var) Ditto.
* get.c: (cmd_get) Use dict_compact_values() instead of a loop.
(trim_dictionary) Use dict_delete_vars(), dict_reorder_vars().
(rename_variables) Use dict_rename_vars().
(mtf_merge_dictionary) Use dict_get_documents(),
dict_set_documents(), dict_compact_values().
* pfm-read.c: (read_variables) Deal with changes to weighting.
* q2c.c: (dump_parser) Use dict_lookup_var() instead of
is_varname() in output code.
* sfm-read.c: (read_header) Use dict_create(), dict_set_label(),
other dictionary functions.
* title.c: (add_document_line) Use dict_get_documents(),
dict_set_documents().
* vars-atr.c: (discard_variables) Use dict_clear(default_dict),
reset default_handle by hand. dict_clear() will clear vectors so
there's no need for that by hand.
* vfm.c: (close_active_file) Move call to finish_compaction()
earlier, so that we can do the compaction as a single step using
dict_compact_values(). Use dict_clear_vectors().
(finish_compaction) Use dict_delete_var(), dict_compact_values().
Some functions don't have replacements:
* vars-atr.c: (force_create_variable) Removed. All references
updated to dict_create_var() followed by an assertion.
(force_dup_variable) Removed. All references updated to
dict_clone_var() followed by an assertion.
* weight.c: (update_weighting) Removed. No longer necessary, so
all references removed.
Sat Dec 27 16:43:01 2003 Ben Pfaff <blp@gnu.org>
Clean up AGGREGATE.
* aggregate.c: Eliminate separation of weighted and unweighted
case. It made the code too obscure and I doubt it was actually
faster. Instead, all code uses the "weighted" code, because
that's a generalization of the "unweighted" code.
(FWEIGHT) Removed.
(FOPTIONS) Ditto.
(parse_aggregate_functions) No need to set FWEIGHT.
(accumulate_aggregate_info) Get rid of FWEIGHT cases.
(dump_aggregate_info) Ditto.
(initialize_aggregate_info) No need for special plain_function
that gets rid of FWEIGHT option.
* aggregate.c: Get rid of approximations.
(accumulate_aggregate_info) Don't use approx_gt(), approx_lt(),
approx_in_range().
(aggregate_single_case) Don't use approx_ne().
Sat Dec 27 16:19:36 2003 Ben Pfaff <blp@gnu.org>
* ascii.c (ascii_line_width): Dead code, removed.
* postscript.c (ps_line_width): Ditto.
* q2c.c (xrealloc): Ditto.
* count.c (internal_cmd_count): Ditto.
* means.q (validate_dependent_endpoint): Ditto.
* set.q: (cmd_gset) Ditto.
* weight.c: [0] (weight_trns_proc) Ditto.
Sat Dec 27 16:18:16 2003 Ben Pfaff <blp@gnu.org>
Make the code -Wmissing-prototypes clean.
* Makefile.am (version.c): Add #include "version.h".
* ascii.c: (ascii_open_global) Make static.
(ascii_close_page) Ditto.
(ascii_font_sizes) Ditto.
(ascii_postopen_driver) Ditto.
(ascii_close_driver) Ditto.
(ascii_option) Ditto.
(ascii_open_page) Ditto.
(ascii_line_horz) Ditto.
(ascii_line_vert) Ditto.
(ascii_line_intersection) Ditto.
(ascii_box) Ditto.
(ascii_polyline_begin) Ditto.
(ascii_polyline_point) Ditto.
(ascii_polyline_end) Ditto.
(ascii_text_set_font_by_name) Ditto.
(ascii_text_set_font_by_position) Ditto.
(ascii_text_set_font_by_family) Ditto.
(ascii_text_get_font_name) Ditto.
(ascii_text_get_font_family) Ditto.
(ascii_text_set_size) Ditto.
(ascii_text_get_size) Ditto.
(ascii_text_metrics) Ditto.
(ascii_text_draw) Ditto.
(ascii_close_page) Ditto.
* cmdline.h: New header for parse_command_line(). Used where
needed.
* command.c: Move prototypes for cmd_*() functions to command.h.
* command.h: Prototypes for cmd_*() functions moved here from
command.c.
* crosstabs.q: (gamma_int) Ditto.
* file-handle.h: Add fh_init_files() prototype.
* getline.c: (welcome) Ditto.
* glob.h: New header for init_glob(). Used where appropriate.
* hash.c: (comparison_helper) Ditto.
* html.c: (html_open_global) Ditto.
(html_close_global) Ditto.
(html_preopen_driver) Ditto.
(html_postopen_driver) Ditto.
(html_close_driver) Ditto.
(html_option) Ditto.
(html_open_page) Ditto.
(html_close_page) Ditto.
(html_submit) Ditto.
* inpt-pgm.c: (input_program_source_read) Ditto.
* output.c: (find_defn_value) Ditto.
(destroy_list) Ditto.
* pfm-read.c: (read_int) Ditto.
* postscript.c: (ps_open_global) Ditto.
(ps_close_global) Ditto.
(ps_font_sizes) Ditto.
(ps_preopen_driver) Ditto.
(ps_postopen_driver) Ditto.
(ps_close_driver) Ditto.
(ps_option) Ditto.
(ps_open_page) Ditto.
(ps_close_page) Ditto.
(ps_line_horz) Ditto.
(ps_line_vert) Ditto.
(ps_line_intersection) Ditto.
(ps_box) Ditto.
(ps_polyline_begin) Ditto.
(ps_polyline_point) Ditto.
(ps_polyline_end) Ditto.
(ps_text_set_font_by_name) Ditto.
(ps_text_set_font_by_position) Ditto.
(ps_text_set_font_family) Ditto.
(ps_text_get_font_name) Ditto.
(ps_text_get_font_family) Ditto.
(ps_text_set_size) Ditto.
(ps_text_get_size) Ditto.
(ps_text_metrics) Ditto.
(ps_text_draw) Ditto.
* q2c.c: (finish_up) Ditto.
(xmalloc) Ditto.
(xstrdup) Ditto.
(get_buffer) Ditto.
(st_lower) Ditto.
(st_upper) Ditto.
(skip_ws) Ditto.
(get_line) Ditto.
(add_symbol) Ditto.
(find_symbol) Ditto.
(lex_get) Ditto.
(force_id) Ditto.
(force_string) Ditto.
(match_id) Ditto.
(match_token) Ditto.
(skip_token) Ditto.
(parse) Ditto.
(parse_setting) Ditto.
(parse_specifier) Ditto.
(parse_specifiers) Ditto.
(parse_subcommand) Ditto.
(dump_specifier_vars) Ditto.
(is_keyword) Ditto.
(make_identifier) Ditto.
(dump_declarations) Ditto.
(dump_specifier_init) Ditto.
(dump_vars_init) Ditto.
(make_match) Ditto.
(dump_specifier_parse) Ditto.
(dump_subcommand) Ditto.
(dump_parser) Ditto.
(dump_header) Ditto.
(dump_free) Ditto.
(recognize_directive) Ditto.
* recode.c: (string_to_long) Ditto.
* repeat.c: (find_DO_REPEAT_substitution) Ditto.
* repeat.h: New header for perform_DO_REPEAT_substitutions, used
where appropriate.
* sort.c: (sort_stream_read) Ditto.
(sort_stream_mode) Ditto.
+Sat Dec 27 16:16:49 2003 Ben Pfaff <blp@gnu.org>
+
+ * configure.ac: Add -Wmissing-prototypes flag to gcc.
+
+ * TODO: Updated.
+
Wed Dec 17 12:19:40 WAST 2003 John Darrington <john@darrington.wattle.id.au>
* Added an --enable-debug flag to configure
-Time-stamp: <2003-12-15 22:51:49 blp>
+Time-stamp: <2003-12-27 12:03:42 blp>
TODO
----
+Probably should get rid of approx.h. The user really needs to be responsible
+for his own precision.
+
Use AFM files instead of Groff font files, and include AFMs for our default
fonts with the distribution.
See if process_active_file() has wider applicability.
-Looks like there's a potential problem with value labels--we use free_val_lab
-from avl_destroy(), but free_val_lab doesn't decrement the reference count, it
-just frees the label. Check into this sometime soon.
-
Eliminate private data in struct variable through use of pointers.
Fix som_columns().
dnl This must be after other tests so warnings don't provoke errors above.
if test "$ac_cv_c_compiler_gnu" = yes; then
CFLAGS="-g -Wall -W -Wno-uninitialized -Wwrite-strings \
--Wstrict-prototypes -Wpointer-arith -Wno-sign-compare"
+-Wstrict-prototypes -Wpointer-arith -Wno-sign-compare -Wmissing-prototypes"
if test "$CC_OPTIONS" != ""; then
CFLAGS="$CFLAGS $CC_OPTIONS"
fi
+Sat Dec 27 22:17:52 2003 Ben Pfaff <blp@gnu.org>
+
+ Dictionary classes: each variable is "ordinary", "system", or
+ "scratch".
+
+ * var.h: (enum dict_class) New enum.
+
+ * vars-prs.c: (dict_class_from_id) New function.
+ (dict_class_to_name) New function.
+
+Sat Dec 27 22:16:06 2003 Ben Pfaff <blp@gnu.org>
+
+ * var.h: (struct freq_tab_set) Removed (not used).
+
+Sat Dec 27 22:15:21 2003 Ben Pfaff <blp@gnu.org>
+
+ * value-labels.c: (val_labs_destroy) vls needs to be freed too.
+
+Sat Dec 27 22:10:49 2003 Ben Pfaff <blp@gnu.org>
+
+ * stats.c: (hypercube) Rename pow4(). All references updated.
+
+Sat Dec 27 22:05:49 2003 Ben Pfaff <blp@gnu.org>
+
+ * rename-vars.c: (cmd_rename_variables) Rewritten.
+ (compare_name) Removed.
+
+Sat Dec 27 22:03:51 2003 Ben Pfaff <blp@gnu.org>
+
+ var_set feature, and code taking advantage of it.
+
+ * crosstabs.q: (static var var_dict) Removed.
+ (static var variables) New variable.
+ (static var variables_cnt) New variable.
+ (cmd_crosstabs) Free variables instead of var_dict.
+ (internal_cmd_crosstabs) Initialize and use variables,
+ variables_cnt instead of var_dict.
+ (free_var_dict) Removed.
+ (crs_custom_tables) Use var_set instead of a copied dictionary.
+ (crs_custom_variables) Set up variables, variables_cnt instead of
+ var_dict.
+ [DEBUGGING] (debug_print) Ditto.
+
+ * means.q: (mns_custom_tables) Use var_set instead of a copied
+ dictionary.
+
+ * vars-prs.c: (parse_vs_variable) New function.
+ (parse_dict_variable) Rewritten.
+ (parse_variable) Rewritten.
+ (parse_variables) Renamed parse_var_set_vars(), rewritten.
+ (parse_variables) New function in terms of parse_var_set_vars().
+ Now requires its first argument to be non-null. All references
+ that passed a null pointer updated to pass default_dict instead.
+ (macro id_dict) Removed.
+ (parse_DATA_LIST_vars) Add assertions.
+ (parse_mixed_vars) Ditto.
+ (struct var_set) New structure.
+ (var_set_get_cnt) New function.
+ (var_set_get_var) New function.
+ (var_set_lookup_var) New function.
+ (var_set_destroy) New function.
+ (dict_var_set_get_cnt) New function.
+ (dict_var_set_get_var) New function.
+ (dict_var_set_lookup_var) New function.
+ (dict_var_set_destroy) New function.
+ (var_set_create_from_dict) New function.
+ (struct array_var_set) New structure.
+ (array_var_set_get_cnt) New function.
+ (array_var_set_get_var) New function.
+ (array_var_set_lookup_var) New function.
+ (array_var_set_destroy) New function.
+ (var_set_create_from_array) New function.
+
+ * q2c.c: (dump_parser) Use parse_variables(default_dict, ...)
+ instead of parse_variables(NULL, ...) in output code.
+
+Sat Dec 27 21:38:53 2003 Ben Pfaff <blp@gnu.org>
+
+ Change inp_init from a 2-bit vector to an ordinary array.
+ Initialize it all in cmd_end_input_program() instead of in
+ create_variable().
+
+ * inpt-pgm.c: (enum value_init_type) New enum.
+ (global var inp_init) Change to `enum value_init_type *', make
+ static.
+ (inp_init_size) Removed.
+ (inp_nval) Change to `size_t', make static.
+ (cmd_input_program) Don't initialize inp_init or inp_init_size.
+ (cmd_end_input_program) Initialize inp_init, inp_nval.
+ (init_case) Rewrite.
+ (clear_case) Rewrite.
+
+ * inpt-pgm.h: Removed.
+
+Sat Dec 27 21:36:38 2003 Ben Pfaff <blp@gnu.org>
+
+ * hash.c: (hsh_hash_bytes) Use Fowler-Noll-Vo hash instead of
+ Colin Plumb hash. It is simpler and should better resist
+ collisions.
+ (hsh_hash_string) Ditto.
+
+Sat Dec 27 21:34:57 2003 Ben Pfaff <blp@gnu.org>
+
+ * get.c: (export_write_case_func) Remove debug printing code.
+
+Sat Dec 27 21:11:09 2003 Ben Pfaff <blp@gnu.org>
+
+ * get.c: (cmd_save_internal) Rename parameter. Use &t->h instead
+ of cast.
+ (save_write_case_func) Use &trns->h instead of cast.
+ (cmd_export) Use &t->h instead of cast.
+
+Sat Dec 27 20:57:42 2003 Ben Pfaff <blp@gnu.org>
+
+ Moved vectors into the dictionary.
+
+ * var.h: (struct vector) Moved here from vector.h. `index' member
+ renamed `idx', `v' renamed `var', `nv' renamed `cnt'. All
+ references updated.
+
+ * vector.h: Removed.
+
+ * vector.c: (global var vec) Removed.
+ (global var nvec) Removed.
+ (cmd_vector) Rewritten.
+ (find_vector) Removed.
+
+ * dictionary.c: (dict_create_vector) New function.
+ (dict_get_vector) New function, replaces reading global vec[]
+ array.
+ (dict_get_vector_cnt) New function, replaces reading global nvec
+ variable.
+ (dict_lookup_vector) New function, replaces find_vector().
+ (dict_clear_vectors) New function.
+
+Sat Dec 27 20:54:01 2003 Ben Pfaff <blp@gnu.org>
+
+ Start to move away from `struct variable' p `union' member to void
+ * aux member.
+
+ * var.h: (struct variable) Add `aux' member.
+
+Sat Dec 27 20:36:25 2003 Ben Pfaff <blp@gnu.org>
+
+ Get rid of struct variable `foo' member.
+
+ * frequencies.q: (internal_cmd_frequencies) Use p.frq.used instead
+ of foo.
+ (frq_custom_variables) Ditto.
+ (frq_custom_grouped) Ditto.
+
+ * get.c: (struct save_trns) Change `var' member from `int *' to
+ `struct variable **'.
+ (cmd_save_internal) Use aux instead of foo.
+ (save_trns_proc) Use revised `var' member.
+ (static var mtf_seq_no) Renamed mtf_seq_num.
+ (static var mtf_seq_nums) New static var.
+ (cmd_match_files) Initialize mtf_seq_nums.
+ (mtf_free) Free mtf_seq_nums.
+ (mtf_processing) Use mtf_seq_nums instead of foo.
+ (mtf_merge_dictionary) No need to initialize mv->foo.
+ (cmd_export) Use aux instead of foo. Use revised `var' member.
+ (mns_custom_tables) Don't use foo to check for duplicates, that's
+ what PV_NO_DUPLICATE is for.
+
+ * var.h: (struct variable) Remove `foo' member.
+ (struct frequencies_proc) New member.
+
+Sat Dec 27 19:46:13 2003 Ben Pfaff <blp@gnu.org>
+
+ Clean up COMPUTE and IF.
+
+ * compute.c: More or less rewrite the darn thing.
+ (struct compute_trns) Rename and reorder and add and delete
+ members.
+ (cmd_compute) Rewrite.
+ (compute_num) Make conditional on test expression. Now used for
+ both COMPUTE and IF.
+ (compute_num_vec) Ditto.
+ (compute_str) Ditto.
+ (compute_str_vec) Ditto.
+ (cmd_if) Rewrite.
+ (if_num) Removed.
+ (if_num_vec) Removed.
+ (if_str) Removed.
+ (if_str_vec) Removed.
+ (parse_target_expression) Renamed parse_rvalue_expression(),
+ rewritten.
+ (new_trns) Renamed compute_trns_create(), rewritten.
+ (delete_trns) Removed.
+ (free_trns) Renamed compute_trns_free(), rewritten.
+ (struct lvalue) New structure.
+ (parse_var_or_vec) Renamed lvalue_parse(), rewritten.
+ (lvalue_get_type) New function.
+ (lvalue_is_vector) New function.
+ (lvalue_finalize) New function.
+ (lvalue_destroy) New function.
+
+Sat Dec 27 19:44:14 2003 Ben Pfaff <blp@gnu.org>
+
+ * command.def: Disallow MODIFY VARS in input mode, so that
+ variables can't get dropped and confuse cmd_end_input_program()'s
+ attempt to fill inp_init[].
+
+ * modify-vars.c: (static var forward_positional_ordering) New
+ variable.
+ (struct var_modification) Entirely changed.
+ (rearrange_dict) Interface changed, rewritten.
+ (cmd_modify_vars) Deal with modified struct var_modification, much
+ rewritten.
+ (struct var_renaming) New structure.
+ (compare_var_renaming_by_new_name) New function.
+ (validate_var_modification) New function.
+
+ * var.h: (struct modify_vars_proc) Removed.
+ (struct variable) Removed member p.mfv.
+
+Sat Dec 27 19:40:26 2003 Ben Pfaff <blp@gnu.org>
+
+ Make EVALUATE a valid command whether we're debugging or not, so
+ that `make check' can succeed regardless of whether debugging is
+ turned on.
+
+ * command.def: [GLOBAL_DEBUGGING] Drop the #if.
+
+ * compute.c: [GLOBAL_DEBUGGING] (cmd_evaluate) Drop the #if.
+
+Sat Dec 27 19:34:40 2003 Ben Pfaff <blp@gnu.org>
+
+ * apply-dict.c: (cmd_apply_dictionary) Replace a ghastly switch
+ statement by a simple if test.
+
+ * dfm.c: (dfm_get_record) Add assertion.
+
+Sat Dec 27 17:51:26 2003 Ben Pfaff <blp@gnu.org>
+
+ For each file x.c, move #include "x.h" to the very top of the
+ include list, to catch x.h failing to include the proper headers.
+
+Sat Dec 27 17:50:19 2003 Ben Pfaff <blp@gnu.org>
+
+ * algorithm.c: (find) New function.
+ (remove_equal) New function.
+ (set_difference) New function.
+ (adjacent_find_equal) New function.
+ [TEST_UNIQUE] Removed test case.
+ (copy_if) Find end test.
+
+Sat Dec 27 17:42:45 2003 Ben Pfaff <blp@gnu.org>
+
+ * dictionary.c: (dict_get_case_weight) New convenience function.
+
+ * aggregate.c: (accumulate_aggregate_info) Use
+ dict_get_case_weight().
+
+ * frequencies.q: (calc_general) Ditto.
+ (calc_integer) Ditto.
+ (calc) Ditto.
+
+ * t-test.q: (groups_calc) Ditto.
+ (z_calc) Ditto.
+
+Sat Dec 27 17:29:45 2003 Ben Pfaff <blp@gnu.org>
+
+ * glob.c: (global var default_dict) Change from `struct
+ dictionary' to `struct dictionary *'. All references changed.
+ (init_glob) Initialize default_dict with dict_create().
+
+Sat Dec 27 17:06:06 2003 Ben Pfaff <blp@gnu.org>
+
+ struct dictionary now made opaque. All related functions:
+
+ * get.c: (rename_variables) Removed.
+ (dict_delete_run) Removed.
+
+ * temporary.c: (copy_variable) Removed.
+ (new_dictionary) Removed.
+ (save_dictionary) Removed.
+ (restore_dictionary) Removed.
+ (free_dictionary) Removed.
+
+ * vars-atr.c: (clear_default_dict) Removed.
+ (find_variable) Removed.
+ (find_dict_variable) Removed.
+ (create_variable) Removed.
+ (delete_variable) Removed.
+ (common_init_stuff) Removed.
+ (init_variable) Removed. Updating of inp_init moved into
+ cmd_end_input_program().
+ (replace_variable) Removed.
+ (rename_variable) Removed.
+ (clear_variable) Removed.
+ (dup_variable) Removed.
+
+ * vars-prs.c: (is_varname) Removed.
+ (is_dict_varname) Removed.
+ (fill_all_vars) Removed.
+
+ * vector.c: (find_vector) Removed.
+
+ * weight.c: (stop_weighting) Removed.
+
+ * dictionary.c: New file.
+ (dict_create) New, replaces new_dictionary().
+ (dict_clone) New, replaces save_dictionary() and
+ restore_dictionary().
+ (dict_clear) New, replaces clear_default_dict().
+ (dict_destroy) New, replaces free_dictionary().
+ (dict_get_var_cnt) New function, replaces references to
+ dict->nvar.
+ (dict_get_var) New function, replaces references to dict->var[i].
+ (dict_get_vars) New function, replaces fill_all_vars().
+ (dict_create_var) New, replaces create_variable(). Interface
+ drops `type' parameter, using a zero `width' to designate numeric.
+ (dict_clone_var) New, replaces dup_variable().
+ (dict_rename_var) New, replaces rename_variable().
+ (dict_lookup_var) New, replaces find_variable(),
+ find_dict_variable(), is_varname().
+ (dict_contains_var) New function.
+ (compare_variable_dblptrs) New function.
+ (dict_delete_var) New function, replaces clear_variable().
+ (dict_delete_vars) New function, replaces dict_delete_run().
+ (dict_reorder_vars) New function.
+ (dict_rename_vars) New function, replaces rename_variables().
+ (dict_get_weight) New function, replaces reading dict->weight_var.
+ (dict_set_weight) New function, replaces writing dict->weight_var
+ or calling stop_weight(dict).
+ (dict_get_filter) New function, replaces reading dict->filter_var.
+ (dict_set_filter) New function, replaces writing dict->filter_var.
+ (dict_get_case_limit) New function, replaces reading dict->N.
+ (dict_set_case_limit) New function, replaces writing dict->N.
+ (dict_get_value_cnt) New function, replaces reading dict->nval.
+ (dict_compact_values) New function, replaces a loop that was
+ replicated in several places.
+ (dict_get_split_vars) New function, replaces reading dict->splits.
+ (dict_get_split_cnt) New function, replaces reading
+ dict->n_splits.
+ (dict_set_split_vars) New function, replaces writing dict->splits.
+ (dict_get_label) New function, replaces reading dict->label.
+ (dict_set_label) New function, replaces writing dict->label.
+ (dict_get_documents) New function, replaces reading
+ dict->documents.
+ (dict_set_documents) New function, replaces writing
+ dict->documents.
+
+ All references to above functions updated.
+
+ * aggregate.c: (cmd_aggregate) Copy file label and documents from
+ old dictionary to new by hand, because dict_create() can't do it
+ itself. Use dict_set_documents(), dict_set_split_vars().
+
+ * temporary.c: (cancel_temporary) Also set temp_dict to NULL after
+ calling dict_destroy().
+
+ * data-list.c: (dls_var_spec) Remove `type' member, replace by
+ `width'.
+ (fixed_parse_compatible) Some slightly nontrivial changes for
+ dict_create_var().
+ (dump_fmt_list) Ditto.
+ (parse_free) Ditto.
+
+ * file-type.c: (create_col_var) Ditto.
+
+ * get.c: (cmd_get) Use dict_compact_values() instead of a loop.
+ (trim_dictionary) Use dict_delete_vars(), dict_reorder_vars().
+ (rename_variables) Use dict_rename_vars().
+ (mtf_merge_dictionary) Use dict_get_documents(),
+ dict_set_documents(), dict_compact_values().
+
+ * pfm-read.c: (read_variables) Deal with changes to weighting.
+
+ * q2c.c: (dump_parser) Use dict_lookup_var() instead of
+ is_varname() in output code.
+
+ * sfm-read.c: (read_header) Use dict_create(), dict_set_label(),
+ other dictionary functions.
+
+ * title.c: (add_document_line) Use dict_get_documents(),
+ dict_set_documents().
+
+ * vars-atr.c: (discard_variables) Use dict_clear(default_dict),
+ reset default_handle by hand. dict_clear() will clear vectors so
+ there's no need for that by hand.
+
+ * vfm.c: (close_active_file) Move call to finish_compaction()
+ earlier, so that we can do the compaction as a single step using
+ dict_compact_values(). Use dict_clear_vectors().
+ (finish_compaction) Use dict_delete_var(), dict_compact_values().
+
+ Some functions don't have replacements:
+
+ * vars-atr.c: (force_create_variable) Removed. All references
+ updated to dict_create_var() followed by an assertion.
+ (force_dup_variable) Removed. All references updated to
+ dict_clone_var() followed by an assertion.
+
+ * weight.c: (update_weighting) Removed. No longer necessary, so
+ all references removed.
+
+Sat Dec 27 16:43:01 2003 Ben Pfaff <blp@gnu.org>
+
+ Clean up AGGREGATE.
+
+ * aggregate.c: Eliminate separation of weighted and unweighted
+ case. It made the code too obscure and I doubt it was actually
+ faster. Instead, all code uses the "weighted" code, because
+ that's a generalization of the "unweighted" code.
+ (FWEIGHT) Removed.
+ (FOPTIONS) Ditto.
+ (parse_aggregate_functions) No need to set FWEIGHT.
+ (accumulate_aggregate_info) Get rid of FWEIGHT cases.
+ (dump_aggregate_info) Ditto.
+ (initialize_aggregate_info) No need for special plain_function
+ that gets rid of FWEIGHT option.
+
+ * aggregate.c: Get rid of approximations.
+ (accumulate_aggregate_info) Don't use approx_gt(), approx_lt(),
+ approx_in_range().
+ (aggregate_single_case) Don't use approx_ne().
+
+Sat Dec 27 16:19:36 2003 Ben Pfaff <blp@gnu.org>
+
+ * ascii.c (ascii_line_width): Dead code, removed.
+
+ * postscript.c (ps_line_width): Ditto.
+
+ * q2c.c (xrealloc): Ditto.
+
+ * count.c (internal_cmd_count): Ditto.
+
+ * means.q (validate_dependent_endpoint): Ditto.
+
+ * set.q: (cmd_gset) Ditto.
+
+ * weight.c: [0] (weight_trns_proc) Ditto.
+
+Sat Dec 27 16:18:16 2003 Ben Pfaff <blp@gnu.org>
+
+ Make the code -Wmissing-prototypes clean.
+
+ * Makefile.am (version.c): Add #include "version.h".
+
+ * ascii.c: (ascii_open_global) Make static.
+ (ascii_close_page) Ditto.
+ (ascii_font_sizes) Ditto.
+ (ascii_postopen_driver) Ditto.
+ (ascii_close_driver) Ditto.
+ (ascii_option) Ditto.
+ (ascii_open_page) Ditto.
+ (ascii_line_horz) Ditto.
+ (ascii_line_vert) Ditto.
+ (ascii_line_intersection) Ditto.
+ (ascii_box) Ditto.
+ (ascii_polyline_begin) Ditto.
+ (ascii_polyline_point) Ditto.
+ (ascii_polyline_end) Ditto.
+ (ascii_text_set_font_by_name) Ditto.
+ (ascii_text_set_font_by_position) Ditto.
+ (ascii_text_set_font_by_family) Ditto.
+ (ascii_text_get_font_name) Ditto.
+ (ascii_text_get_font_family) Ditto.
+ (ascii_text_set_size) Ditto.
+ (ascii_text_get_size) Ditto.
+ (ascii_text_metrics) Ditto.
+ (ascii_text_draw) Ditto.
+ (ascii_close_page) Ditto.
+
+ * cmdline.h: New header for parse_command_line(). Used where
+ needed.
+
+ * command.c: Move prototypes for cmd_*() functions to command.h.
+
+ * command.h: Prototypes for cmd_*() functions moved here from
+ command.c.
+
+ * crosstabs.q: (gamma_int) Ditto.
+
+ * file-handle.h: Add fh_init_files() prototype.
+
+ * getline.c: (welcome) Ditto.
+
+ * glob.h: New header for init_glob(). Used where appropriate.
+
+ * hash.c: (comparison_helper) Ditto.
+
+ * html.c: (html_open_global) Ditto.
+ (html_close_global) Ditto.
+ (html_preopen_driver) Ditto.
+ (html_postopen_driver) Ditto.
+ (html_close_driver) Ditto.
+ (html_option) Ditto.
+ (html_open_page) Ditto.
+ (html_close_page) Ditto.
+ (html_submit) Ditto.
+
+ * inpt-pgm.c: (input_program_source_read) Ditto.
+
+ * output.c: (find_defn_value) Ditto.
+ (destroy_list) Ditto.
+
+ * pfm-read.c: (read_int) Ditto.
+
+ * postscript.c: (ps_open_global) Ditto.
+ (ps_close_global) Ditto.
+ (ps_font_sizes) Ditto.
+ (ps_preopen_driver) Ditto.
+ (ps_postopen_driver) Ditto.
+ (ps_close_driver) Ditto.
+ (ps_option) Ditto.
+ (ps_open_page) Ditto.
+ (ps_close_page) Ditto.
+ (ps_line_horz) Ditto.
+ (ps_line_vert) Ditto.
+ (ps_line_intersection) Ditto.
+ (ps_box) Ditto.
+ (ps_polyline_begin) Ditto.
+ (ps_polyline_point) Ditto.
+ (ps_polyline_end) Ditto.
+ (ps_text_set_font_by_name) Ditto.
+ (ps_text_set_font_by_position) Ditto.
+ (ps_text_set_font_family) Ditto.
+ (ps_text_get_font_name) Ditto.
+ (ps_text_get_font_family) Ditto.
+ (ps_text_set_size) Ditto.
+ (ps_text_get_size) Ditto.
+ (ps_text_metrics) Ditto.
+ (ps_text_draw) Ditto.
+
+ * q2c.c: (finish_up) Ditto.
+ (xmalloc) Ditto.
+ (xstrdup) Ditto.
+ (get_buffer) Ditto.
+ (st_lower) Ditto.
+ (st_upper) Ditto.
+ (skip_ws) Ditto.
+ (get_line) Ditto.
+ (add_symbol) Ditto.
+ (find_symbol) Ditto.
+ (lex_get) Ditto.
+ (force_id) Ditto.
+ (force_string) Ditto.
+ (match_id) Ditto.
+ (match_token) Ditto.
+ (skip_token) Ditto.
+ (parse) Ditto.
+ (parse_setting) Ditto.
+ (parse_specifier) Ditto.
+ (parse_specifiers) Ditto.
+ (parse_subcommand) Ditto.
+ (dump_specifier_vars) Ditto.
+ (is_keyword) Ditto.
+ (make_identifier) Ditto.
+ (dump_declarations) Ditto.
+ (dump_specifier_init) Ditto.
+ (dump_vars_init) Ditto.
+ (make_match) Ditto.
+ (dump_specifier_parse) Ditto.
+ (dump_subcommand) Ditto.
+ (dump_parser) Ditto.
+ (dump_header) Ditto.
+ (dump_free) Ditto.
+ (recognize_directive) Ditto.
+
+ * recode.c: (string_to_long) Ditto.
+
+ * repeat.c: (find_DO_REPEAT_substitution) Ditto.
+
+ * repeat.h: New header for perform_DO_REPEAT_substitutions, used
+ where appropriate.
+
+ * sort.c: (sort_stream_read) Ditto.
+ (sort_stream_mode) Ditto.
+
Fri Dec 19 23:35:04 2003 Ben Pfaff <blp@gnu.org>
* algorithm.c (binary_search): Fix comparison.
pspp_SOURCES = aggregate.c algorithm.c algorithm.h alloc.c alloc.h \
apply-dict.c approx.h ascii.c autorecode.c bitvector.h cases.c cases.h \
-cmdline.c command.c command.def command.h compute.c correlations.c \
-count.c crosstabs.c data-in.c data-in.h data-list.c data-out.c \
-debug-print.h descript.c dfm.c dfm.h do-if.c do-ifP.h error.c error.h \
-expr-evl.c expr-opt.c expr-prs.c expr.h exprP.h file-handle.c \
-file-handle.h file-type.c filename.c filename.h flip.c font.h format.c \
-format.def format.h formats.c frequencies.c get.c getline.c getline.h \
-glob.c groff-font.c hash.c hash.h heap.c heap.h html.c htmlP.h \
-include.c inpt-pgm.c inpt-pgm.h lexer.c lexer.h list.c log.h loop.c \
-magic.c magic.h main.c main.h matrix-data.c matrix.c matrix.h means.c \
-mis-val.c misc.c misc.h modify-vars.c numeric.c output.c output.h \
-pfm-read.c pfm-write.c pfm.h pool.c pool.h postscript.c print.c \
-random.c random.h recode.c rename-vars.c repeat.c sample.c sel-if.c \
-set.c settings.h sfm-read.c sfm-write.c sfm.h sfmP.h som.c som.h \
-sort.c sort.h split-file.c stat.h stats.c stats.h str.c str.h \
-sysfile-info.c tab.c tab.h temporary.c title.c t-test.c val-labs.c \
-value-labels.c value-labels.h var-labs.c var.h vars-atr.c vars-prs.c \
-vector.c vector.h version.c version.h vfm.c vfm.h vfmP.h weight.c
+cmdline.c cmdline.h command.c command.def command.h compute.c \
+correlations.c count.c crosstabs.c data-in.c data-in.h data-list.c \
+data-out.c debug-print.h descript.c dfm.c dfm.h dictionary.c do-if.c \
+do-ifP.h error.c error.h expr-evl.c expr-opt.c expr-prs.c expr.h \
+exprP.h file-handle.c file-handle.h file-type.c filename.c filename.h \
+flip.c font.h format.c format.def format.h formats.c frequencies.c \
+get.c getline.c getline.h glob.c glob.h groff-font.c hash.c hash.h \
+heap.c heap.h html.c htmlP.h include.c inpt-pgm.c lexer.c lexer.h \
+list.c log.h loop.c magic.c magic.h main.c main.h matrix-data.c \
+matrix.c matrix.h means.c mis-val.c misc.c misc.h modify-vars.c \
+numeric.c output.c output.h pfm-read.c pfm-write.c pfm.h pool.c pool.h \
+postscript.c print.c random.c random.h recode.c rename-vars.c repeat.c \
+repeat.h sample.c sel-if.c set.c settings.h sfm-read.c sfm-write.c \
+sfm.h sfmP.h som.c som.h sort.c sort.h split-file.c stat.h stats.c \
+stats.h str.c str.h sysfile-info.c tab.c tab.h temporary.c title.c \
+t-test.c val-labs.c value-labels.c value-labels.h var-labs.c var.h \
+vars-atr.c vars-prs.c vector.c version.c version.h vfm.c vfm.h vfmP.h \
+weight.c
pspp_LDADD = ../lib/julcal/libjulcal.a \
../lib/misc/libmisc.a \
version.c:
echo "#include <config.h>" > version.c
+ echo "#include \"version.h\"" > version.c
echo "const char bare_version[] = \"@VERSION@\";" >> version.c
echo "const char version[] = \"GNU @PACKAGE@ @VERSION@\";" >> version.c
echo "const char stat_version[] = \"GNU @PACKAGE@ @VERSION@ \
#include <assert.h>
#include <stdlib.h>
#include "alloc.h"
-#include "approx.h"
#include "command.h"
#include "error.h"
#include "file-handle.h"
N_AGR_FUNCS, N_NO_VARS, NU_NO_VARS,
FUNC = 0x1f, /* Function mask. */
FSTRING = 1<<5, /* String function bit. */
- FWEIGHT = 1<<6, /* Weighted function bit. */
- FOPTIONS = FSTRING | FWEIGHT /* Function options mask. */
};
/* Attributes of an aggregation function. */
v_sort = NULL;
prev_case = NULL;
- agr_dict = new_dictionary (1);
+ agr_dict = dict_create ();
+ dict_set_label (agr_dict, dict_get_label (default_dict));
+ dict_set_documents (agr_dict, dict_get_documents (default_dict));
lex_match_id ("AGGREGATE");
if (seen & 1)
{
free (v_sort);
- free_dictionary (agr_dict);
+ dict_destroy (agr_dict);
msg (SE, _("OUTFILE specified multiple times."));
return CMD_FAILURE;
}
if (outfile == NULL)
{
free (v_sort);
- free_dictionary (agr_dict);
+ dict_destroy (agr_dict);
return CMD_FAILURE;
}
}
if (!lex_match_id ("COLUMNWISE"))
{
free (v_sort);
- free_dictionary (agr_dict);
+ dict_destroy (agr_dict);
lex_error (_("while expecting COLUMNWISE"));
return CMD_FAILURE;
}
if (seen & 8)
{
free (v_sort);
- free_dictionary (agr_dict);
+ dict_destroy (agr_dict);
msg (SE, _("BREAK specified multiple times."));
return CMD_FAILURE;
}
lex_match ('=');
if (!parse_sort_variables ())
{
- free_dictionary (agr_dict);
+ dict_destroy (agr_dict);
return CMD_FAILURE;
}
{
struct variable *v;
- v = dup_variable (agr_dict, v_sort[i], v_sort[i]->name);
+ v = dict_clone_var (agr_dict, v_sort[i], v_sort[i]->name);
assert (v != NULL);
}
}
/* Delete documents. */
if (!(seen & 2))
- {
- free (agr_dict->documents);
- agr_dict->documents = NULL;
- agr_dict->n_documents = 0;
- }
+ dict_set_documents (agr_dict, NULL);
/* Cancel SPLIT FILE. */
- default_dict.n_splits = 0;
- free (default_dict.splits);
- default_dict.splits = NULL;
+ dict_set_split_vars (agr_dict, NULL, 0);
#if DEBUGGING
debug_print (seen);
{
free_aggregate_functions ();
free (v_sort);
- free_dictionary (agr_dict);
+ dict_destroy (agr_dict);
return 0;
}
buf64_1xx = xmalloc (sizeof *buf64_1xx * w.case_size);
- buf_1xx = xmalloc (sizeof (struct ccase) + sizeof (union value) * (agr_dict->nval - 1));
+ buf_1xx = xmalloc (sizeof (struct ccase)
+ + (sizeof (union value)
+ * (dict_get_value_cnt (agr_dict) - 1)));
return 1;
}
{
agr_first = agr_next = NULL;
- /* Anticipate weighting for optimization later. */
- update_weighting (&default_dict);
-
/* Parse everything. */
for (;;)
{
else if (function->n_args)
pv_opts |= PV_SAME_TYPE;
- if (!parse_variables (&default_dict, &src, &n_src, pv_opts))
+ if (!parse_variables (default_dict, &src, &n_src, pv_opts))
goto lossage;
}
if (src)
{
- int output_type;
+ int output_width;
agr_next->src = src[i];
agr_next->string = xmalloc (src[i]->width);
}
- if (default_dict.weight_index != -1)
- agr_next->function |= FWEIGHT;
-
- if (agr_next->src->type == NUMERIC)
- output_type = NUMERIC;
+ if (agr_next->src->type == NUMERIC || function->alpha_type == NUMERIC)
+ output_width = 0;
else
- output_type = function->alpha_type;
+ output_width = agr_next->src->width;
if (function->alpha_type == ALPHA)
- destvar = dup_variable (agr_dict, agr_next->src, dest[i]);
+ destvar = dict_clone_var (agr_dict, agr_next->src, dest[i]);
else
{
- destvar = create_variable (agr_dict, dest[i], output_type,
- agr_next->src->width);
- if (output_type == NUMERIC)
+ destvar = dict_create_var (agr_dict, dest[i], output_width);
+ if (output_width == 0)
destvar->print = destvar->write = function->format;
- if (output_type == NUMERIC && default_dict.weight_index != -1
+ if (output_width == 0 && dict_get_weight (default_dict) != NULL
&& (func_index == N || func_index == N_NO_VARS
|| func_index == NU || func_index == NU_NO_VARS))
{
}
} else {
agr_next->src = NULL;
- destvar = create_variable (agr_dict, dest[i], NUMERIC, 0);
+ destvar = dict_create_var (agr_dict, dest[i], 0);
}
if (!destvar)
struct agr_var *iter, *next;
if (agr_dict)
- free_dictionary (agr_dict);
+ dict_destroy (agr_dict);
for (iter = agr_first; iter; iter = next)
{
next = iter->next;
switch (v->type)
{
case NUMERIC:
- if (approx_ne (input->data[v->fv].f, iter->f))
+ if (input->data[v->fv].f != iter->f)
goto not_equal;
iter++;
break;
accumulate_aggregate_info (struct ccase *input)
{
struct agr_var *iter;
+ double weight;
-#define WEIGHT (input->data[default_dict.weight_index].f)
+ weight = dict_get_case_weight (default_dict, input);
for (iter = agr_first; iter; iter = iter->next)
if (iter->src)
{
switch (iter->function)
{
- case NMISS | FWEIGHT:
- iter->dbl[0] += WEIGHT;
- break;
case NMISS:
+ iter->dbl[0] += weight;
+ break;
case NUMISS:
- case NUMISS | FWEIGHT:
iter->int1++;
break;
}
switch (iter->function)
{
case SUM:
- case SUM | FWEIGHT:
iter->dbl[0] += v->f;
break;
case MEAN:
- iter->dbl[0] += v->f;
- iter->int1++;
- break;
- case MEAN | FWEIGHT:
- {
- double w = WEIGHT;
- iter->dbl[0] += v->f * w;
- iter->dbl[1] += w;
- break;
- }
- case SD:
- iter->dbl[0] += v->f;
- iter->dbl[1] += v->f * v->f;
- iter->int1++;
- break;
- case SD | FWEIGHT:
- {
- double w = WEIGHT;
- double product = v->f * w;
- iter->dbl[0] += product;
- iter->dbl[1] += product * v->f;
- iter->dbl[2] += w;
- break;
- }
+ iter->dbl[0] += v->f * weight;
+ iter->dbl[1] += weight;
+ break;
+ case SD:
+ {
+ double product = v->f * weight;
+ iter->dbl[0] += product;
+ iter->dbl[1] += product * v->f;
+ iter->dbl[2] += weight;
+ break;
+ }
case MAX:
- case MAX | FWEIGHT:
iter->dbl[0] = max (iter->dbl[0], v->f);
iter->int1 = 1;
break;
case MAX | FSTRING:
- case MAX | FSTRING | FWEIGHT:
if (memcmp (iter->string, v->s, iter->src->width) < 0)
memcpy (iter->string, v->s, iter->src->width);
iter->int1 = 1;
break;
case MIN:
- case MIN | FWEIGHT:
iter->dbl[0] = min (iter->dbl[0], v->f);
iter->int1 = 1;
break;
case MIN | FSTRING:
- case MIN | FSTRING | FWEIGHT:
if (memcmp (iter->string, v->s, iter->src->width) > 0)
memcpy (iter->string, v->s, iter->src->width);
iter->int1 = 1;
break;
case FGT:
case PGT:
- if (approx_gt (v->f, iter->arg[0].f))
- iter->int1++;
- iter->int2++;
- break;
- case FGT | FWEIGHT:
- case PGT | FWEIGHT:
- {
- double w = WEIGHT;
- if (approx_gt (v->f, iter->arg[0].f))
- iter->dbl[0] += w;
- iter->dbl[1] += w;
- break;
- }
+ if (v->f > iter->arg[0].f)
+ iter->dbl[0] += weight;
+ iter->dbl[1] += weight;
+ break;
case FGT | FSTRING:
case PGT | FSTRING:
- if (memcmp (iter->arg[0].c, v->s, iter->src->width) < 0)
- iter->int1++;
- iter->int2++;
- break;
- case FGT | FSTRING | FWEIGHT:
- case PGT | FSTRING | FWEIGHT:
- {
- double w = WEIGHT;
- if (memcmp (iter->arg[0].c, v->s, iter->src->width) < 0)
- iter->dbl[0] += w;
- iter->dbl[1] += w;
- break;
- }
+ if (memcmp (iter->arg[0].c, v->s, iter->src->width) < 0)
+ iter->dbl[0] += weight;
+ iter->dbl[1] += weight;
+ break;
case FLT:
case PLT:
- if (approx_lt (v->f, iter->arg[0].f))
- iter->int1++;
- iter->int2++;
- break;
- case FLT | FWEIGHT:
- case PLT | FWEIGHT:
- {
- double w = WEIGHT;
- if (approx_lt (v->f, iter->arg[0].f))
- iter->dbl[0] += w;
- iter->dbl[1] += w;
- break;
- }
+ if (v->f < iter->arg[0].f)
+ iter->dbl[0] += weight;
+ iter->dbl[1] += weight;
+ break;
case FLT | FSTRING:
case PLT | FSTRING:
- if (memcmp (iter->arg[0].c, v->s, iter->src->width) > 0)
- iter->int1++;
- iter->int2++;
- break;
- case FLT | FSTRING | FWEIGHT:
- case PLT | FSTRING | FWEIGHT:
- {
- double w = WEIGHT;
- if (memcmp (iter->arg[0].c, v->s, iter->src->width) > 0)
- iter->dbl[0] += w;
- iter->dbl[1] += w;
- break;
- }
+ if (memcmp (iter->arg[0].c, v->s, iter->src->width) > 0)
+ iter->dbl[0] += weight;
+ iter->dbl[1] += weight;
+ break;
case FIN:
case PIN:
- if (approx_in_range (v->f, iter->arg[0].f, iter->arg[1].f))
- iter->int1++;
- iter->int2++;
- break;
- case FIN | FWEIGHT:
- case PIN | FWEIGHT:
- {
- double w = WEIGHT;
- if (approx_in_range (v->f, iter->arg[0].f, iter->arg[1].f))
- iter->dbl[0] += w;
- iter->dbl[1] += w;
- break;
- }
+ if (iter->arg[0].f <= v->f && v->f <= iter->arg[1].f)
+ iter->dbl[0] += weight;
+ iter->dbl[1] += weight;
+ break;
case FIN | FSTRING:
case PIN | FSTRING:
- if (memcmp (iter->arg[0].c, v->s, iter->src->width) <= 0
- && memcmp (iter->arg[1].c, v->s, iter->src->width) >= 0)
- iter->int1++;
- iter->int2++;
- break;
- case FIN | FSTRING | FWEIGHT:
- case PIN | FSTRING | FWEIGHT:
- {
- double w = WEIGHT;
- if (memcmp (iter->arg[0].c, v->s, iter->src->width) <= 0
- && memcmp (iter->arg[1].c, v->s, iter->src->width) >= 0)
- iter->dbl[0] += w;
- iter->dbl[1] += w;
- break;
- }
+ if (memcmp (iter->arg[0].c, v->s, iter->src->width) <= 0
+ && memcmp (iter->arg[1].c, v->s, iter->src->width) >= 0)
+ iter->dbl[0] += weight;
+ iter->dbl[1] += weight;
+ break;
case FOUT:
case POUT:
- if (!approx_in_range (v->f, iter->arg[0].f, iter->arg[1].f))
- iter->int1++;
- iter->int2++;
- break;
- case FOUT | FWEIGHT:
- case POUT | FWEIGHT:
- {
- double w = WEIGHT;
- if (!approx_in_range (v->f, iter->arg[0].f, iter->arg[1].f))
- iter->dbl[0] += w;
- iter->dbl[1] += w;
- break;
- }
+ if (iter->arg[0].f > v->f || v->f > iter->arg[1].f)
+ iter->dbl[0] += weight;
+ iter->dbl[1] += weight;
+ break;
case FOUT | FSTRING:
case POUT | FSTRING:
- if (memcmp (iter->arg[0].c, v->s, iter->src->width) > 0
- && memcmp (iter->arg[1].c, v->s, iter->src->width) < 0)
- iter->int1++;
- iter->int2++;
- break;
- case FOUT | FSTRING | FWEIGHT:
- case POUT | FSTRING | FWEIGHT:
- {
- double w = WEIGHT;
- if (memcmp (iter->arg[0].c, v->s, iter->src->width) > 0
- && memcmp (iter->arg[1].c, v->s, iter->src->width) < 0)
- iter->dbl[0] += w;
- iter->dbl[1] += w;
- break;
- }
- case N | FWEIGHT:
- iter->dbl[0] += WEIGHT;
- break;
+ if (memcmp (iter->arg[0].c, v->s, iter->src->width) > 0
+ && memcmp (iter->arg[1].c, v->s, iter->src->width) < 0)
+ iter->dbl[0] += weight;
+ iter->dbl[1] += weight;
+ break;
case N:
+ iter->dbl[0] += weight;
+ break;
case NU:
- case NU | FWEIGHT:
iter->int1++;
break;
case FIRST:
- case FIRST | FWEIGHT:
if (iter->int1 == 0)
{
iter->dbl[0] = v->f;
}
break;
case FIRST | FSTRING:
- case FIRST | FSTRING | FWEIGHT:
if (iter->int1 == 0)
{
memcpy (iter->string, v->s, iter->src->width);
}
break;
case LAST:
- case LAST | FWEIGHT:
iter->dbl[0] = v->f;
iter->int1 = 1;
break;
case LAST | FSTRING:
- case LAST | FSTRING | FWEIGHT:
memcpy (iter->string, v->s, iter->src->width);
iter->int1 = 1;
break;
} else {
switch (iter->function)
{
- case N_NO_VARS | FWEIGHT:
- iter->dbl[0] += WEIGHT;
- break;
case N_NO_VARS:
+ iter->dbl[0] += weight;
+ break;
case NU_NO_VARS:
- case NU_NO_VARS | FWEIGHT:
iter->int1++;
break;
default:
switch (i->function)
{
case SUM:
- case SUM | FWEIGHT:
v->f = i->dbl[0];
break;
case MEAN:
- v->f = i->int1 ? i->dbl[0] / i->int1 : SYSMIS;
- break;
- case MEAN | FWEIGHT:
v->f = i->dbl[1] != 0.0 ? i->dbl[0] / i->dbl[1] : SYSMIS;
break;
case SD:
- v->f = ((i->int1 > 1)
- ? calc_stddev (calc_variance (i->dbl, i->int1))
- : SYSMIS);
- break;
- case SD | FWEIGHT:
v->f = ((i->dbl[2] > 1.0)
? calc_stddev (calc_variance (i->dbl, i->dbl[2]))
: SYSMIS);
break;
case MAX:
- case MAX | FWEIGHT:
case MIN:
- case MIN | FWEIGHT:
v->f = i->int1 ? i->dbl[0] : SYSMIS;
break;
case MAX | FSTRING:
- case MAX | FSTRING | FWEIGHT:
case MIN | FSTRING:
- case MIN | FSTRING | FWEIGHT:
if (i->int1)
memcpy (v->s, i->string, i->dest->width);
else
memset (v->s, ' ', i->dest->width);
break;
- case FGT:
case FGT | FSTRING:
- case FLT:
case FLT | FSTRING:
- case FIN:
case FIN | FSTRING:
- case FOUT:
case FOUT | FSTRING:
v->f = i->int2 ? (double) i->int1 / (double) i->int2 : SYSMIS;
break;
- case FGT | FWEIGHT:
- case FGT | FSTRING | FWEIGHT:
- case FLT | FWEIGHT:
- case FLT | FSTRING | FWEIGHT:
- case FIN | FWEIGHT:
- case FIN | FSTRING | FWEIGHT:
- case FOUT | FWEIGHT:
- case FOUT | FSTRING | FWEIGHT:
+ case FGT:
+ case FLT:
+ case FIN:
+ case FOUT:
v->f = i->dbl[1] ? i->dbl[0] / i->dbl[1] : SYSMIS;
break;
case PGT:
case PIN | FSTRING:
case POUT:
case POUT | FSTRING:
- v->f = (i->int2
- ? (double) i->int1 / (double) i->int2 * 100.0
- : SYSMIS);
- break;
- case PGT | FWEIGHT:
- case PGT | FSTRING | FWEIGHT:
- case PLT | FWEIGHT:
- case PLT | FSTRING | FWEIGHT:
- case PIN | FWEIGHT:
- case PIN | FSTRING | FWEIGHT:
- case POUT | FWEIGHT:
- case POUT | FSTRING | FWEIGHT:
v->f = i->dbl[1] ? i->dbl[0] / i->dbl[1] * 100.0 : SYSMIS;
break;
- case N | FWEIGHT:
- v->f = i->dbl[0];
case N:
+ v->f = i->dbl[0];
+ break;
case NU:
- case NU | FWEIGHT:
v->f = i->int1;
break;
case FIRST:
- case FIRST | FWEIGHT:
case LAST:
- case LAST | FWEIGHT:
v->f = i->int1 ? i->dbl[0] : SYSMIS;
break;
case FIRST | FSTRING:
- case FIRST | FSTRING | FWEIGHT:
case LAST | FSTRING:
- case LAST | FSTRING | FWEIGHT:
if (i->int1)
memcpy (v->s, i->string, i->dest->width);
else
memset (v->s, ' ', i->dest->width);
break;
- case N_NO_VARS | FWEIGHT:
+ case N_NO_VARS:
v->f = i->dbl[0];
break;
- case N_NO_VARS:
case NU_NO_VARS:
- case NU_NO_VARS | FWEIGHT:
v->f = i->int1;
break;
- case NMISS | FWEIGHT:
+ case NMISS:
v->f = i->dbl[0];
break;
- case NMISS:
case NUMISS:
- case NUMISS | FWEIGHT:
v->f = i->int1;
break;
default:
for (iter = agr_first; iter; iter = iter->next)
{
- int plain_function = iter->function & ~FWEIGHT;
-
iter->missing = 0;
- switch (plain_function)
+ switch (iter->function)
{
case MIN:
iter->dbl[0] = DBL_MAX;
flt64 *p = buf64_1xx;
int i;
- for (i = 0; i < agr_dict->nvar; i++)
+ for (i = 0; i < dict_get_var_cnt (agr_dict); i++)
{
- struct variable *v = agr_dict->var[i];
+ struct variable *v = dict_get_var (agr_dict, i);
if (v->type == NUMERIC)
{
* purpose. It is provided "as is" without express or implied warranty.
*/
+/* Copyright (C) 1991, 1992, 1996, 1997, 1999 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
#include <config.h>
+#include "algorithm.h"
#include <assert.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include "alloc.h"
-#include "algorithm.h"
#include "random.h"
\f
+/* Finds an element in ARRAY, which contains COUNT elements of
+ SIZE bytes each, using COMPARE for comparisons. Returns the
+ first element in ARRAY that matches TARGET, or a null pointer
+ on failure. AUX is passed to each comparison as auxiliary
+ data. */
+void *find (const void *array, size_t count, size_t size,
+ const void *target,
+ algo_compare_func *compare, void *aux)
+{
+ const unsigned char *element = array;
+
+ while (count-- > 0)
+ {
+ if (compare (target, element, aux) == 0)
+ return (void *) element;
+
+ element += size;
+ }
+
+ return NULL;
+}
+\f
/* Byte-wise swap two items of size SIZE. */
-#define SWAP(a, b, size) \
- do \
- { \
- register size_t __size = (size); \
- register char *__a = (a), *__b = (b); \
- do \
- { \
- char __tmp = *__a; \
- *__a++ = *__b; \
- *__b++ = __tmp; \
- } while (--__size > 0); \
+#define SWAP(a, b, size) \
+ do \
+ { \
+ register size_t __size = (size); \
+ register char *__a = (a), *__b = (b); \
+ do \
+ { \
+ char __tmp = *__a; \
+ *__a++ = *__b; \
+ *__b++ = __tmp; \
+ } while (--__size > 0); \
} while (0)
/* Makes the elements in ARRAY unique, by moving up duplicates,
sort (array, count, size, compare, aux);
return unique (array, count, size, compare, aux);
}
-
-#ifdef TEST_UNIQUE
-#include <stdio.h>
-
-void *
-xmalloc (size_t size)
-{
- return malloc (size);
-}
-
-int
-compare_ints (const void *a_, const void *b_, void *aux)
-{
- const int *a = a_;
- const int *b = b_;
-
- if (*a > *b)
- return 1;
- else if (*a < *b)
- return 1;
- else
- return 0;
-}
-
-void
-try_unique (const char *title,
- int *in, size_t in_cnt,
- size_t out_cnt)
-{
- size_t i;
-
- in_cnt = unique (in, in_cnt, sizeof *in, compare_ints, NULL);
- if (in_cnt != out_cnt)
- {
- fprintf (stderr, "unique_test: %s: in_cnt %d, expected %d\n",
- title, (int) in_cnt, (int) out_cnt);
- return;
- }
-
- for (i = 0; i < out_cnt; i++)
- {
- if (in[i] != i)
- fprintf (stderr, "unique_test: %s: idx %d = %d, expected %d\n",
- title, (int) i, in[i], i);
- }
-}
-
-int
-main (void)
-{
- int a_in[] = {0, 0, 0, 1, 2, 3, 3, 4, 5, 5};
- int b_in[] = {0, 1, 2, 2, 2, 3};
- int c_in[] = {0};
- int d_in;
-
- try_unique ("a", a_in, sizeof a_in / sizeof *a_in, 6);
- try_unique ("b", b_in, sizeof b_in / sizeof *b_in, 4);
- try_unique ("c", c_in, sizeof c_in / sizeof *c_in, 1);
- try_unique ("d", &d_in, 0, 0);
-
-}
-#endif /* TEST_UNIQUE */
\f
/* Reorders ARRAY, which contains COUNT elements of SIZE bytes
each, so that the elements for which PREDICATE returns nonzero
const unsigned char *last = input + size * count;
unsigned char *output = result;
- while (input <= last)
+ while (input < last)
{
if (predicate (input, aux))
{
return !pred_aux->predicate (data, pred_aux->aux);
}
+/* Removes elements equal to ELEMENT from ARRAY, which consists
+ of COUNT elements of SIZE bytes each. Returns the number of
+ remaining elements. AUX is passed to COMPARE as auxiliary
+ data. */
+size_t
+remove_equal (void *array, size_t count, size_t size,
+ void *element,
+ algo_compare_func *compare, void *aux)
+{
+ unsigned char *first = array;
+ unsigned char *last = first + count * size;
+ unsigned char *result;
+
+ for (;;)
+ {
+ if (first >= last)
+ return count;
+ if (compare (first, element, aux) == 0)
+ break;
+
+ first += size;
+ }
+
+ result = first;
+ count--;
+ for (;;)
+ {
+ first += size;
+ if (first >= last)
+ return count;
+
+ if (compare (first, element, aux) == 0)
+ {
+ count--;
+ continue;
+ }
+
+ memcpy (result, first, size);
+ result += size;
+ }
+
+ return count;
+}
+
/* Copies the COUNT elements of SIZE bytes each from ARRAY to
RESULT, except that elements for which PREDICATE is true are
not copied. Returns the number of elements copied. AUX is
return count1 < count2 ? -1 : count1 > count2;
}
-
\f
-/* Copyright (C) 1991, 1992, 1996, 1997, 1999 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
/* If you consider tuning this algorithm, you should consult first:
Engineering a sort function; Jon Bentley and M. Douglas McIlroy;
Software - Practice and Experience; Vol. 23 (11), 1249-1265, 1993. */
}
}
}
+\f
+/* Computes the generalized set difference, ARRAY1 minus ARRAY2,
+ into RESULT, and returns the number of elements written to
+ RESULT. If a value appears M times in ARRAY1 and N times in
+ ARRAY2, then it will appear max(M - N, 0) in RESULT. ARRAY1
+ and ARRAY2 must be sorted, and RESULT is sorted and stable.
+ ARRAY1 consists of COUNT1 elements, ARRAY2 of COUNT2 elements,
+ each SIZE bytes. AUX is passed to COMPARE as auxiliary
+ data. */
+size_t set_difference (const void *array1, size_t count1,
+ const void *array2, size_t count2,
+ size_t size,
+ void *result_,
+ algo_compare_func *compare, void *aux)
+{
+ const unsigned char *first1 = array1;
+ const unsigned char *last1 = first1 + count1 * size;
+ const unsigned char *first2 = array2;
+ const unsigned char *last2 = first2 + count2 * size;
+ unsigned char *result = result_;
+ size_t result_count = 0;
+
+ while (first1 != last1 && first2 != last2)
+ {
+ int cmp = compare (first1, first2, aux);
+ if (cmp < 0)
+ {
+ memcpy (result, first1, size);
+ first1 += size;
+ result += size;
+ result_count++;
+ }
+ else if (cmp > 0)
+ first2 += size;
+ else
+ {
+ first1 += size;
+ first2 += size;
+ }
+ }
+
+ while (first1 != last1)
+ {
+ memcpy (result, first1, size);
+ first1 += size;
+ result += size;
+ result_count++;
+ }
+
+ return result_count;
+}
+\f
+/* Finds the first pair of adjacent equal elements in ARRAY,
+ which has COUNT elements of SIZE bytes. Returns the first
+ element in ARRAY such that COMPARE returns zero when it and
+ its successor element are compared, or a null pointer if no
+ such element exists. AUX is passed to COMPARE as auxiliary
+ data. */
+void *
+adjacent_find_equal (const void *array, size_t count, size_t size,
+ algo_compare_func *compare, void *aux)
+{
+ const unsigned char *first = array;
+ const unsigned char *last = first + count * size;
+
+ while (first < last && first + size < last)
+ {
+ if (compare (first, first + size, aux) == 0)
+ return (void *) first;
+ first += size;
+ }
+
+ return NULL;
+}
+
/* A generally suitable random function. */
algo_random_func algo_default_random;
+/* Finds an element in ARRAY, which contains COUNT elements of
+ SIZE bytes each, using COMPARE for comparisons. Returns the
+ first element in ARRAY that matches TARGET, or a null pointer
+ on failure. AUX is passed to each comparison as auxiliary
+ data. */
+void *find (const void *array, size_t count, size_t size,
+ const void *target,
+ algo_compare_func *compare, void *aux);
+
/* Sorts ARRAY, which contains COUNT elements of SIZE bytes each,
using COMPARE for comparisons. AUX is passed to each
comparison as auxiliary data. */
void *result,
algo_predicate_func *predicate, void *aux);
+/* Removes elements equal to ELEMENT from ARRAY, which consists
+ of COUNT elements of SIZE bytes each. Returns the number of
+ remaining elements. AUX is passed to COMPARE as auxiliary
+ data. */
+size_t remove_equal (void *array, size_t count, size_t size,
+ void *element,
+ algo_compare_func *compare, void *aux);
+
/* Copies the COUNT elements of SIZE bytes each from ARRAY to
RESULT, except that elements for which PREDICATE is true are
not copied. Returns the number of elements copied. AUX is
size_t size,
algo_compare_func *compare, void *aux);
+/* Computes the generalized set difference, ARRAY1 minus ARRAY2,
+ into RESULT, and returns the number of elements written to
+ RESULT. If a value appears M times in ARRAY1 and N times in
+ ARRAY2, then it will appear max(M - N, 0) in RESULT. ARRAY1
+ and ARRAY2 must be sorted, and RESULT is sorted and stable.
+ ARRAY1 consists of COUNT1 elements, ARRAY2 of COUNT2 elements,
+ each SIZE bytes. AUX is passed to COMPARE as auxiliary
+ data. */
+size_t set_difference (const void *array1, size_t count1,
+ const void *array2, size_t count2,
+ size_t size,
+ void *result,
+ algo_compare_func *compare, void *aux);
+
+/* Finds the first pair of adjacent equal elements in ARRAY,
+ which has COUNT elements of SIZE bytes. Returns the first
+ element in ARRAY such that COMPARE returns zero when it and
+ its successor element are compared. AUX is passed to COMPARE
+ as auxiliary data. */
+void *adjacent_find_equal (const void *array, size_t count, size_t size,
+ algo_compare_func *compare, void *aux);
+
#endif /* sort-algo.h */
02111-1307, USA. */
#include <config.h>
+#include "alloc.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
if (dict == NULL)
return CMD_FAILURE;
- for (i = 0; i < dict->nvar; i++)
+ for (i = 0; i < dict_get_var_cnt (dict); i++)
{
- struct variable *s = dict->var[i];
- struct variable *t = find_variable (s->name);
+ struct variable *s = dict_get_var (dict, i);
+ struct variable *t = dict_lookup_var (default_dict, s->name);
if (t == NULL)
continue;
t->miss_type = s->miss_type;
memcpy (t->missing, s->missing, sizeof s->missing);
}
+ skip_missing_values: ;
if (s->type == NUMERIC)
{
"and target files."));
/* Weighting. */
- {
- const int tfw = find_variable (default_dict.weight_var) != 0;
- const int sfw = dict->weight_var[0] != 0;
- struct variable *w;
-
- switch (10 * tfw + sfw)
- {
- case 10:
- /* The working file retains its weighting variable. */
- break;
-
- case 00:
- case 01:
- /* Fall through to case 11. */
-
- case 11:
- w = find_variable (dict->weight_var);
- if (w)
- strcpy (default_dict.weight_var, dict->weight_var);
- break;
- }
- }
- skip_missing_values: ;
+ if (dict_get_weight (dict) != NULL)
+ {
+ struct variable *new_weight
+ = dict_lookup_var (default_dict, dict_get_weight (dict)->name);
+
+ if (new_weight != NULL)
+ dict_set_weight (default_dict, new_weight);
+ }
sfm_maybe_close (handle);
static int postopen (struct file_ext *);
static int preclose (struct file_ext *);
-int
+static int
ascii_open_global (struct outp_class *this unused)
{
ascii_pool = pool_create ();
return 1;
}
-int
+static int
ascii_close_global (struct outp_class *this unused)
{
pool_destroy (ascii_pool);
return 1;
}
-int *
+static int *
ascii_font_sizes (struct outp_class *this unused, int *n_valid_sizes)
{
static int valid_sizes[] = {12, 12, 0, 0};
return valid_sizes;
}
-int
+static int
ascii_preopen_driver (struct outp_driver *this)
{
struct ascii_driver_ext *x;
return 1;
}
-int
+static int
ascii_postopen_driver (struct outp_driver *this)
{
struct ascii_driver_ext *x = this->ext;
return 1;
}
-int
+static int
ascii_close_driver (struct outp_driver *this)
{
struct ascii_driver_ext *x = this->ext;
};
static struct outp_option_info option_info;
-void
+static void
ascii_option (struct outp_driver *this, const char *key,
const struct string *val)
{
return 1;
}
-int
+static int
ascii_open_page (struct outp_driver *this)
{
struct ascii_driver_ext *x = this->ext;
#define B(STYLE) (STYLE<<LNS_BOTTOM)
#define R(STYLE) (STYLE<<LNS_RIGHT)
-void
+static void
ascii_line_horz (struct outp_driver *this, const struct rect *r,
const struct color *c unused, int style)
{
draw_line (x, y1, (style << LNS_LEFT) | (style << LNS_RIGHT));
}
-void
+static void
ascii_line_vert (struct outp_driver *this, const struct rect *r,
const struct color *c unused, int style)
{
draw_line (x1, y, (style << LNS_TOP) | (style << LNS_BOTTOM));
}
-void
+static void
ascii_line_intersection (struct outp_driver *this, const struct rect *r,
const struct color *c unused,
const struct outp_styles *style)
draw_line (x, y, l);
}
-void
-ascii_line_width (struct outp_driver *this, int *width, int *height)
-{
- int i;
-
- assert (this->driver_open && this->page_open);
- width[0] = height[0] = 0;
- for (i = 1; i < OUTP_L_COUNT; i++)
- {
- width[i] = this->horiz;
- height[i] = this->vert;
- }
-}
-
/* FIXME: Later we could set this up so that for certain devices it
performs shading? */
-void
+static void
ascii_box (struct outp_driver *this unused, const struct rect *r unused,
const struct color *bord unused, const struct color *fill unused)
{
}
/* Polylines not supported. */
-void
+static void
ascii_polyline_begin (struct outp_driver *this unused, const struct color *c unused)
{
assert (this->driver_open && this->page_open);
}
-void
+static void
ascii_polyline_point (struct outp_driver *this unused, int x unused, int y unused)
{
assert (this->driver_open && this->page_open);
}
-void
+static void
ascii_polyline_end (struct outp_driver *this unused)
{
assert (this->driver_open && this->page_open);
}
-void
+static void
ascii_text_set_font_by_name (struct outp_driver * this, const char *s)
{
struct ascii_driver_ext *x = this->ext;
x->cur_font = OUTP_F_B;
}
-void
+static void
ascii_text_set_font_by_position (struct outp_driver *this, int pos)
{
struct ascii_driver_ext *x = this->ext;
x->cur_font = pos >= 0 && pos < 4 ? pos : 0;
}
-void
+static void
ascii_text_set_font_by_family (struct outp_driver *this unused, const char *s unused)
{
assert (this->driver_open && this->page_open);
}
-const char *
+static const char *
ascii_text_get_font_name (struct outp_driver *this)
{
struct ascii_driver_ext *x = this->ext;
abort ();
}
-const char *
+static const char *
ascii_text_get_font_family (struct outp_driver *this unused)
{
assert (this->driver_open && this->page_open);
return "";
}
-int
+static int
ascii_text_set_size (struct outp_driver *this, int size)
{
assert (this->driver_open && this->page_open);
return size == this->vert;
}
-int
+static int
ascii_text_get_size (struct outp_driver *this, int *em_width)
{
assert (this->driver_open && this->page_open);
t->v = (temp.y * this->vert) - t->y;
}
-void
+static void
ascii_text_metrics (struct outp_driver *this, struct outp_text *t)
{
assert (this->driver_open && this->page_open);
delineate (this, t, 0);
}
-void
+static void
ascii_text_draw (struct outp_driver *this, struct outp_text *t)
{
/* FIXME: orientations not supported. */
}
}
-int
+static int
ascii_close_page (struct outp_driver *this)
{
static unsigned char *s;
lex_match_id ("AUTORECODE");
lex_match_id ("VARIABLES");
lex_match ('=');
- if (!parse_variables (&default_dict, &v_src, &nv_src, PV_NO_DUPLICATE))
+ if (!parse_variables (default_dict, &v_src, &nv_src, PV_NO_DUPLICATE))
return CMD_FAILURE;
if (!lex_force_match_id ("INTO"))
return CMD_FAILURE;
{
int j;
- if (is_varname (n_dest[i]))
+ if (dict_lookup_var (default_dict, n_dest[i]) != NULL)
{
msg (SE, _("Target variable %s duplicates existing variable %s."),
n_dest[i], n_dest[i]);
for (i = 0; i < nv_dest; i++)
{
- v_dest[i] = force_create_variable (&default_dict, n_dest[i], NUMERIC, 0);
+ v_dest[i] = dict_create_var (default_dict, n_dest[i], 0);
+ assert (v_dest[i] != NULL);
free (n_dest[i]);
}
free (n_dest);
02111-1307, USA. */
#include <config.h>
+#include "cmdline.h"
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
--- /dev/null
+/* PSPP - computes sample statistics.
+ Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Written by Ben Pfaff <blp@gnu.org>.
+
+ 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 the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#if !INCLUDED_CMDLINE_H
+#define INCLUDED_CMDLINE_H 1
+
+void parse_command_line (int argc, char **argv);
+
+#endif /* cmdline.h */
#endif
#include <assert.h>
+#include "command.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include "alloc.h"
-#include "command.h"
#include "error.h"
#include "getline.h"
#include "lexer.h"
struct command *next; /* Next command with same word[0]. */
};
-/* Prototype all the command functions. */
-#define DEFCMD(NAME, T1, T2, T3, T4, FUNC) \
- int FUNC (void);
-#define UNIMPL(NAME, T1, T2, T3, T4)
-#include "command.def"
-#undef DEFCMD
-#undef UNIMPL
-
/* Define the command array. */
#define DEFCMD(NAME, T1, T2, T3, T4, FUNC) \
{NAME, {T1, T2, T3, T4}, FUNC, {NULL, NULL, NULL}, NULL},
x = lex_integer ();
lex_get ();
if (!lex_match_id ("ESTIMATED"))
- default_dict.N = x;
+ dict_set_case_limit (default_dict, x);
return lex_end_of_command ();
}
DEFCMD ("END LOOP", ERRO, INPU, TRAN, TRAN, cmd_end_loop)
DEFCMD ("END REPEAT", ERRO, INPU, TRAN, TRAN, cmd_end_repeat)
DEFCMD ("ERASE", INIT, INPU, TRAN, PROC, cmd_erase)
-#if GLOBAL_DEBUGGING
DEFCMD ("EVALUATE", INIT, INPU, TRAN, PROC, cmd_evaluate)
-#endif
DEFCMD ("EXECUTE", ERRO, ERRO, PROC, PROC, cmd_execute)
DEFCMD ("EXIT", INIT, INPU, TRAN, PROC, cmd_exit)
DEFCMD ("EXPORT", ERRO, ERRO, PROC, PROC, cmd_export)
DEFCMD ("MATRIX DATA", TRAN, ERRO, TRAN, TRAN, cmd_matrix_data)
DEFCMD ("MEANS", ERRO, ERRO, PROC, PROC, cmd_means)
DEFCMD ("MISSING VALUES", ERRO, INPU, TRAN, TRAN, cmd_missing_values)
-DEFCMD ("MODIFY VARS", ERRO, INPU, TRAN, PROC, cmd_modify_vars)
+DEFCMD ("MODIFY VARS", ERRO, ERRO, TRAN, PROC, cmd_modify_vars)
DEFCMD ("NEW FILE", INIT, ERRO, INIT, INIT, cmd_new_file)
DEFCMD ("N OF CASES", INIT, INPU, TRAN, TRAN, cmd_n_of_cases)
UNIMPL ("NUMBERED", INIT, INPU, TRAN, PROC)
void cmd_init (void);
int cmd_parse (void);
+/* Prototype all the command functions. */
+#define DEFCMD(NAME, T1, T2, T3, T4, FUNC) \
+ int FUNC (void);
+#define UNIMPL(NAME, T1, T2, T3, T4)
+#include "command.def"
+#undef DEFCMD
+#undef UNIMPL
+
#endif /* !command_h */
02111-1307, USA. */
#include <config.h>
+#include <assert.h>
#include <stdlib.h>
#include "alloc.h"
#include "approx.h"
#include "lexer.h"
#include "str.h"
#include "var.h"
-#include "vector.h"
-/* I can't think of any really good reason to disable debugging for
- this module. */
-#include "debug-print.h"
+struct compute_trns;
+struct lvalue;
+
+/* Target of a COMPUTE or IF assignment, either a variable or a
+ vector element. */
+static struct lvalue *lvalue_parse (void);
+static int lvalue_get_type (const struct lvalue *);
+static int lvalue_is_vector (const struct lvalue *);
+static void lvalue_finalize (struct lvalue *,
+ struct compute_trns *);
+static void lvalue_destroy (struct lvalue *);
/* COMPUTE and IF transformation. */
struct compute_trns
{
struct trns_header h;
- /* Destination. (Used only during parsing.) */
- struct variable *v; /* Destvar, if dest isn't a vector elem. */
- int created; /* Whether we created the destvar (used only during
- parsing). */
+ /* Test expression (IF only). */
+ struct expression *test; /* Test expression. */
+
+ /* Variable lvalue, if variable != NULL. */
+ struct variable *variable; /* Destination variable, if any. */
+ int fv; /* `value' index of destination variable. */
+ int width; /* Lvalue string width; 0=numeric. */
- /* Destination. (Used during execution.) */
- struct vector *vec; /* Destination vector, if dest is a vector elem. */
- int fv; /* `value' index of destination variable. */
- int width; /* Target variable width (string vars only). */
+ /* Vector lvalue, if vector != NULL. */
+ const struct vector *vector; /* Destination vector, if any. */
+ struct expression *element; /* Destination vector element expr. */
- /* Expressions. */
- struct expression *vec_elem; /* Destination vector element expr. */
- struct expression *target; /* Target expression. */
- struct expression *test; /* Test expression (IF only). */
+ /* Rvalue. */
+ struct expression *rvalue; /* Rvalue expression. */
};
-static int parse_target_expression (struct compute_trns *,
- int (*func_tab[4]) (struct trns_header *, struct ccase *));
-static struct compute_trns *new_trns (void);
-static void delete_trns (struct compute_trns *);
-static void free_trns (struct trns_header *);
-static int parse_var_or_vec (struct compute_trns *);
+static int parse_rvalue_expression (struct compute_trns *,
+ const struct lvalue *);
+static struct compute_trns *compute_trns_create (void);
+static void compute_trns_free (struct trns_header *);
\f
/* COMPUTE. */
-static int compute_num (struct trns_header *, struct ccase *);
-static int compute_str (struct trns_header *, struct ccase *);
-static int compute_num_vec (struct trns_header *, struct ccase *);
-static int compute_str_vec (struct trns_header *, struct ccase *);
-
int
cmd_compute (void)
{
- /* Table of functions to process data. */
- static int (*func_tab[4]) (struct trns_header *, struct ccase *) =
- {
- compute_num,
- compute_str,
- compute_num_vec,
- compute_str_vec,
- };
-
- /* Transformation being constructed. */
- struct compute_trns *c;
+ struct lvalue *lvalue = NULL;
+ struct compute_trns *compute = NULL;
lex_match_id ("COMPUTE");
- c = new_trns ();
- if (!parse_var_or_vec (c))
+ lvalue = lvalue_parse ();
+ if (lvalue == NULL)
goto fail;
- if (!lex_force_match ('=')
- || !parse_target_expression (c, func_tab))
+ compute = compute_trns_create ();
+
+ if (!lex_force_match ('=') || !parse_rvalue_expression (compute, lvalue))
goto fail;
- /* Goofy behavior, but compatible: Turn off LEAVE on the destvar. */
- if (c->v && c->v->left && c->v->name[0] != '#')
- {
- devector (c->v);
- c->v->left = 0;
- envector (c->v);
- }
+ lvalue_finalize (lvalue, compute);
- add_transformation ((struct trns_header *) c);
+ add_transformation (&compute->h);
return CMD_SUCCESS;
-fail:
- delete_trns (c);
+ fail:
+ lvalue_destroy (lvalue);
+ if (compute != NULL)
+ {
+ compute_trns_free (&compute->h);
+ free (compute);
+ }
return CMD_FAILURE;
}
+\f
+/* Transformation functions. */
static int
-compute_num (struct trns_header * pt, struct ccase * c)
+compute_num (struct trns_header *compute_, struct ccase *c)
{
- struct compute_trns *t = (struct compute_trns *) pt;
- expr_evaluate (t->target, c, &c->data[t->fv]);
+ struct compute_trns *compute = (struct compute_trns *) compute_;
+
+ if (compute->test == NULL
+ || expr_evaluate (compute->test, c, NULL) == 1.0)
+ {
+ expr_evaluate (compute->rvalue, c, &c->data[compute->fv]);
+ }
+
return -1;
}
static int
-compute_num_vec (struct trns_header * pt, struct ccase * c)
+compute_num_vec (struct trns_header *compute_, struct ccase *c)
{
- struct compute_trns *t = (struct compute_trns *) pt;
+ struct compute_trns *compute = (struct compute_trns *) compute_;
- /* Index into the vector. */
- union value index;
+ if (compute->test == NULL
+ || expr_evaluate (compute->test, c, NULL) == 1.0)
+ {
+ /* Index into the vector. */
+ union value index;
- /* Rounded index value. */
- int rindx;
+ /* Rounded index value. */
+ int rindx;
- expr_evaluate (t->vec_elem, c, &index);
- rindx = floor (index.f + EPSILON);
- if (index.f == SYSMIS || rindx < 1 || rindx > t->vec->nv)
- {
- if (index.f == SYSMIS)
- msg (SW, _("When executing COMPUTE: SYSMIS is not a valid value as "
- "an index into vector %s."), t->vec->name);
- else
- msg (SW, _("When executing COMPUTE: %g is not a valid value as "
- "an index into vector %s."), index.f, t->vec->name);
- return -1;
+ expr_evaluate (compute->element, c, &index);
+ rindx = floor (index.f + EPSILON);
+ if (index.f == SYSMIS || rindx < 1 || rindx > compute->vector->cnt)
+ {
+ if (index.f == SYSMIS)
+ msg (SW, _("When executing COMPUTE: SYSMIS is not a valid value as "
+ "an index into vector %s."), compute->vector->name);
+ else
+ msg (SW, _("When executing COMPUTE: %g is not a valid value as "
+ "an index into vector %s."),
+ index.f, compute->vector->name);
+ return -1;
+ }
+ expr_evaluate (compute->rvalue, c,
+ &c->data[compute->vector->var[rindx - 1]->fv]);
}
- expr_evaluate (t->target, c, &c->data[t->vec->v[rindx - 1]->fv]);
+
return -1;
}
static int
-compute_str (struct trns_header * pt, struct ccase * c)
+compute_str (struct trns_header *compute_, struct ccase *c)
{
- struct compute_trns *t = (struct compute_trns *) pt;
+ struct compute_trns *compute = (struct compute_trns *) compute_;
- /* Temporary storage for string expression return value. */
- union value v;
+ if (compute->test == NULL
+ || expr_evaluate (compute->test, c, NULL) == 1.0)
+ {
+ /* Temporary storage for string expression return value. */
+ union value v;
- expr_evaluate (t->target, c, &v);
- st_bare_pad_len_copy (c->data[t->fv].s, &v.c[1], t->width, v.c[0]);
+ expr_evaluate (compute->rvalue, c, &v);
+ st_bare_pad_len_copy (c->data[compute->fv].s, &v.c[1], compute->width,
+ v.c[0]);
+ }
+
return -1;
}
static int
-compute_str_vec (struct trns_header * pt, struct ccase * c)
+compute_str_vec (struct trns_header *compute_, struct ccase *c)
{
- struct compute_trns *t = (struct compute_trns *) pt;
+ struct compute_trns *compute = (struct compute_trns *) compute_;
- /* Temporary storage for string expression return value. */
- union value v;
+ if (compute->test == NULL
+ || expr_evaluate (compute->test, c, NULL) == 1.0)
+ {
+ /* Temporary storage for string expression return value. */
+ union value v;
- /* Index into the vector. */
- union value index;
+ /* Index into the vector. */
+ union value index;
- /* Rounded index value. */
- int rindx;
+ /* Rounded index value. */
+ int rindx;
- /* Variable reference by indexed vector. */
- struct variable *vr;
+ /* Variable reference by indexed vector. */
+ struct variable *vr;
- expr_evaluate (t->vec_elem, c, &index);
- rindx = floor (index.f + EPSILON);
- if (index.f == SYSMIS || rindx < 1 || rindx > t->vec->nv)
- {
- if (index.f == SYSMIS)
- msg (SW, _("When executing COMPUTE: SYSMIS is not a valid value as "
- "an index into vector %s."), t->vec->name);
- else
- msg (SW, _("When executing COMPUTE: %g is not a valid value as "
- "an index into vector %s."), index.f, t->vec->name);
- return -1;
+ expr_evaluate (compute->element, c, &index);
+ rindx = floor (index.f + EPSILON);
+ if (index.f == SYSMIS || rindx < 1 || rindx > compute->vector->cnt)
+ {
+ if (index.f == SYSMIS)
+ msg (SW, _("When executing COMPUTE: SYSMIS is not a valid "
+ "value as an index into vector %s."),
+ compute->vector->name);
+ else
+ msg (SW, _("When executing COMPUTE: %g is not a valid value as "
+ "an index into vector %s."),
+ index.f, compute->vector->name);
+ return -1;
+ }
+
+ expr_evaluate (compute->rvalue, c, &v);
+ vr = compute->vector->var[rindx - 1];
+ st_bare_pad_len_copy (c->data[vr->fv].s, &v.c[1], vr->width, v.c[0]);
}
-
- expr_evaluate (t->target, c, &v);
- vr = t->vec->v[rindx - 1];
- st_bare_pad_len_copy (c->data[vr->fv].s, &v.c[1], vr->width, v.c[0]);
+
return -1;
}
\f
/* IF. */
-static int if_num (struct trns_header *, struct ccase *);
-static int if_str (struct trns_header *, struct ccase *);
-static int if_num_vec (struct trns_header *, struct ccase *);
-static int if_str_vec (struct trns_header *, struct ccase *);
-
int
cmd_if (void)
{
- /* Table of functions to process data. */
- static int (*func_tab[4]) (struct trns_header *, struct ccase *) =
- {
- if_num,
- if_str,
- if_num_vec,
- if_str_vec,
- };
-
- /* Transformation being constructed. */
- struct compute_trns *c;
+ struct compute_trns *compute = NULL;
+ struct lvalue *lvalue = NULL;
lex_match_id ("IF");
- c = new_trns ();
+ compute = compute_trns_create ();
/* Test expression. */
- c->test = expr_parse (PXP_BOOLEAN);
- if (!c->test)
+ compute->test = expr_parse (PXP_BOOLEAN);
+ if (compute->test == NULL)
goto fail;
- /* Target variable. */
- if (!parse_var_or_vec (c))
+ /* Lvalue variable. */
+ lvalue = lvalue_parse ();
+ if (lvalue == NULL)
goto fail;
- /* Target expression. */
-
- if (!lex_force_match ('=')
- || !parse_target_expression (c, func_tab))
+ /* Rvalue expression. */
+ if (!lex_force_match ('=') || !parse_rvalue_expression (compute, lvalue))
goto fail;
- add_transformation ((struct trns_header *) c);
-
- return CMD_SUCCESS;
-
-fail:
- delete_trns (c);
- return CMD_FAILURE;
-}
-
-static int
-if_num (struct trns_header * pt, struct ccase * c)
-{
- struct compute_trns *t = (struct compute_trns *) pt;
-
- if (expr_evaluate (t->test, c, NULL) == 1.0)
- expr_evaluate (t->target, c, &c->data[t->fv]);
- return -1;
-}
-
-static int
-if_str (struct trns_header * pt, struct ccase * c)
-{
- struct compute_trns *t = (struct compute_trns *) pt;
-
- if (expr_evaluate (t->test, c, NULL) == 1.0)
- {
- union value v;
-
- expr_evaluate (t->target, c, &v);
- st_bare_pad_len_copy (c->data[t->fv].s, &v.c[1], t->width, v.c[0]);
- }
- return -1;
-}
-
-static int
-if_num_vec (struct trns_header * pt, struct ccase * c)
-{
- struct compute_trns *t = (struct compute_trns *) pt;
-
- if (expr_evaluate (t->test, c, NULL) == 1.0)
- {
- /* Index into the vector. */
- union value index;
-
- /* Rounded index value. */
- int rindx;
+ lvalue_finalize (lvalue, compute);
- expr_evaluate (t->vec_elem, c, &index);
- rindx = floor (index.f + EPSILON);
- if (index.f == SYSMIS || rindx < 1 || rindx > t->vec->nv)
- {
- if (index.f == SYSMIS)
- msg (SW, _("When executing COMPUTE: SYSMIS is not a valid value as "
- "an index into vector %s."), t->vec->name);
- else
- msg (SW, _("When executing COMPUTE: %g is not a valid value as "
- "an index into vector %s."), index.f, t->vec->name);
- return -1;
- }
- expr_evaluate (t->target, c,
- &c->data[t->vec->v[rindx]->fv]);
- }
- return -1;
-}
+ add_transformation (&compute->h);
-static int
-if_str_vec (struct trns_header * pt, struct ccase * c)
-{
- struct compute_trns *t = (struct compute_trns *) pt;
+ return CMD_SUCCESS;
- if (expr_evaluate (t->test, c, NULL) == 1.0)
+ fail:
+ lvalue_destroy (lvalue);
+ if (compute != NULL)
{
- /* Index into the vector. */
- union value index;
-
- /* Rounded index value. */
- int rindx;
-
- /* Temporary storage for result of target expression. */
- union value v2;
-
- /* Variable reference by indexed vector. */
- struct variable *vr;
-
- expr_evaluate (t->vec_elem, c, &index);
- rindx = floor (index.f + EPSILON);
- if (index.f == SYSMIS || rindx < 1 || rindx > t->vec->nv)
- {
- if (index.f == SYSMIS)
- msg (SW, _("When executing COMPUTE: SYSMIS is not a valid value as "
- "an index into vector %s."), t->vec->name);
- else
- msg (SW, _("When executing COMPUTE: %g is not a valid value as "
- "an index into vector %s."), index.f, t->vec->name);
- return -1;
- }
- expr_evaluate (t->target, c, &v2);
- vr = t->vec->v[rindx - 1];
- st_bare_pad_len_copy (c->data[vr->fv].s, &v2.c[1], vr->width, v2.c[0]);
+ compute_trns_free (&compute->h);
+ free (compute);
}
- return -1;
+ return CMD_FAILURE;
}
\f
/* Code common to COMPUTE and IF. */
command terminator, sets the case-handling proc from the array
passed. */
static int
-parse_target_expression (struct compute_trns *c,
- int (*proc_list[4]) (struct trns_header *, struct ccase *))
+parse_rvalue_expression (struct compute_trns *compute,
+ const struct lvalue *lvalue)
{
- int dest_type = c->v ? c->v->type : c->vec->v[0]->type;
- c->target = expr_parse (dest_type == ALPHA ? PXP_STRING : PXP_NUMERIC);
- if (!c->target)
+ int type = lvalue_get_type (lvalue);
+ int vector = lvalue_is_vector (lvalue);
+
+ assert (type == NUMERIC || type == ALPHA);
+
+ compute->rvalue = expr_parse (type == ALPHA ? PXP_STRING : PXP_NUMERIC);
+ if (compute->rvalue == NULL)
return 0;
- c->h.proc = proc_list[(dest_type == ALPHA) + 2 * (c->vec != NULL)];
+ if (type == NUMERIC)
+ compute->h.proc = vector ? compute_num_vec : compute_num;
+ else
+ compute->h.proc = vector ? compute_str_vec : compute_str;
if (token != '.')
{
/* Returns a new struct compute_trns after initializing its fields. */
static struct compute_trns *
-new_trns (void)
+compute_trns_create (void)
{
- struct compute_trns *c = xmalloc (sizeof *c);
- c->h.proc = NULL;
- c->h.free = free_trns;
- c->v = NULL;
- c->created = 0;
- c->vec = NULL;
- c->fv = 0;
- c->width = 0;
- c->vec_elem = NULL;
- c->target = NULL;
- c->test = NULL;
- return c;
+ struct compute_trns *compute = xmalloc (sizeof *compute);
+ compute->h.proc = NULL;
+ compute->h.free = compute_trns_free;
+ compute->test = NULL;
+ compute->variable = NULL;
+ compute->vector = NULL;
+ compute->element = NULL;
+ compute->rvalue = NULL;
+ return compute;
}
-/* Deletes all the fields in C, the variable C->v if we created it,
- and C itself. */
+/* Deletes all the fields in COMPUTE. */
static void
-delete_trns (struct compute_trns * c)
+compute_trns_free (struct trns_header *compute_)
{
- free_trns ((struct trns_header *) c);
- if (c->created)
- delete_variable (&default_dict, c->v);
- free (c);
+ struct compute_trns *compute = (struct compute_trns *) compute_;
+
+ expr_free (compute->test);
+ expr_free (compute->element);
+ expr_free (compute->rvalue);
}
+\f
+struct lvalue
+ {
+ char var_name[9]; /* Destination variable name, or "". */
+ const struct vector *vector; /* Destination vector, if any, or NULL. */
+ struct expression *element; /* Destination vector element, or NULL. */
+ };
-/* Deletes all the fields in C. */
-static void
-free_trns (struct trns_header * pt)
+static struct lvalue *
+lvalue_parse (void)
{
- struct compute_trns *t = (struct compute_trns *) pt;
+ struct lvalue *lvalue;
- expr_free (t->vec_elem);
- expr_free (t->target);
- expr_free (t->test);
-}
+ lvalue = xmalloc (sizeof *lvalue);
+ lvalue->var_name[0] = '\0';
+ lvalue->vector = NULL;
+ lvalue->element = NULL;
-/* Parses a variable name or a vector element into C. If the
- variable does not exist, it is created. Returns success. */
-static int
-parse_var_or_vec (struct compute_trns * c)
-{
if (!lex_force_id ())
- return 0;
+ goto lossage;
if (lex_look_ahead () == '(')
{
- /* Vector element. */
- c->vec = find_vector (tokid);
- if (!c->vec)
+ /* Vector. */
+ lvalue->vector = dict_lookup_vector (default_dict, tokid);
+ if (lvalue->vector == NULL)
{
msg (SE, _("There is no vector named %s."), tokid);
- return 0;
+ goto lossage;
}
-
+
+ /* Vector element. */
lex_get ();
if (!lex_force_match ('('))
- return 0;
- c->vec_elem = expr_parse (PXP_NUMERIC);
- if (!c->vec_elem)
- return 0;
+ goto lossage;
+ lvalue->element = expr_parse (PXP_NUMERIC);
+ if (lvalue->element == NULL)
+ goto lossage;
if (!lex_force_match (')'))
- {
- expr_free (c->vec_elem);
- return 0;
- }
+ goto lossage;
}
else
{
/* Variable name. */
- c->v = find_variable (tokid);
- if (!c->v)
- {
- c->v = force_create_variable (&default_dict, tokid, NUMERIC, 0);
- envector (c->v);
- c->created = 1;
- }
- c->fv = c->v->fv;
- c->width = c->v->width;
+ strncpy (lvalue->var_name, tokid, 8);
+ lvalue->var_name[8] = '\0';
lex_get ();
}
- return 1;
+ return lvalue;
+
+ lossage:
+ lvalue_destroy (lvalue);
+ return NULL;
+}
+
+static int
+lvalue_get_type (const struct lvalue *lvalue)
+{
+ if (lvalue->vector == NULL)
+ {
+ struct variable *var
+ = dict_lookup_var (default_dict, lvalue->var_name);
+ if (var == NULL)
+ return NUMERIC;
+ else
+ return var->type;
+ }
+ else
+ return lvalue->vector->var[0]->type;
+}
+
+static int
+lvalue_is_vector (const struct lvalue *lvalue)
+{
+ return lvalue->vector != NULL;
+}
+
+static void
+lvalue_finalize (struct lvalue *lvalue,
+ struct compute_trns *compute)
+{
+ if (lvalue->vector == NULL)
+ {
+ compute->variable = dict_lookup_var (default_dict, lvalue->var_name);
+ if (compute->variable == NULL)
+ compute->variable = dict_create_var (default_dict, lvalue->var_name,
+ 0);
+ assert (compute->variable != NULL);
+
+ compute->fv = compute->variable->fv;
+ compute->width = compute->variable->width;
+
+ /* Goofy behavior, but compatible: Turn off LEAVE. */
+ if (compute->variable->left
+ && dict_class_from_id (compute->variable->name) != DC_SCRATCH)
+ {
+ devector (compute->variable);
+ compute->variable->left = 0;
+ envector (compute->variable);
+ }
+ }
+ else
+ {
+ compute->vector = lvalue->vector;
+ compute->element = lvalue->element;
+ lvalue->element = NULL;
+ }
+
+ lvalue_destroy (lvalue);
+}
+
+static void
+lvalue_destroy (struct lvalue *lvalue)
+{
+ expr_free (lvalue->element);
+ free (lvalue);
}
\f
/* EVALUATE. */
-#if GLOBAL_DEBUGGING
int
cmd_evaluate (void)
{
return CMD_SUCCESS;
}
-#endif
struct cor_set *cor;
/* Ensure that this is a VARIABLES subcommand. */
- if (!lex_match_id ("VARIABLES") && (token != T_ID || !is_varname (tokid))
+ if (!lex_match_id ("VARIABLES")
+ && (token != T_ID || dict_lookup_var (default_dict, tokid) != NULL)
&& token != T_ALL)
return 2;
lex_match ('=');
- if (!parse_variables (&default_dict, &v1, &nv1,
+ if (!parse_variables (default_dict, &v1, &nv1,
PV_NO_DUPLICATE | PV_NUMERIC))
return 0;
if (lex_match (T_WITH))
{
- if (!parse_variables (&default_dict, &v2, &nv2,
+ if (!parse_variables (default_dict, &v2, &nv2,
PV_NO_DUPLICATE | PV_NUMERIC))
{
free (v1);
free (cor);
}
}
+
+/*
+ Local Variables:
+ mode: c
+ End:
+*/
static int parse_numeric_criteria (struct counting *);
static int parse_string_criteria (struct counting *);
-int cmd_count (void);
-
-int
-internal_cmd_count (void)
-{
- int code = cmd_count ();
- if (!code)
- {
- struct count_trns c;
- c.specs = head;
- count_trns_free ((struct trns_header *) & c);
- }
- return code;
-}
-
int
cmd_count (void)
{
/* Get destination struct variable, or at least its name. */
if (!lex_force_id ())
goto fail;
- cnt->d = find_variable (tokid);
+ cnt->d = dict_lookup_var (default_dict, tokid);
if (cnt->d)
{
if (cnt->d->type == ALPHA)
{
c->next = NULL;
c->v = NULL;
- if (!parse_variables (NULL, &c->v, &c->n, PV_DUPLICATE | PV_SAME_TYPE))
+ if (!parse_variables (default_dict, &c->v, &c->n,
+ PV_DUPLICATE | PV_SAME_TYPE))
goto fail;
if (!lex_force_match ('('))
for (cnt = head; cnt; cnt = cnt->next)
if (!cnt->d)
{
- /* It's legal, though motivationally questionable, to count to
+ /* It's valid, though motivationally questionable, to count to
the same dest var more than once. */
- cnt->d = find_variable (cnt->n);
+ cnt->d = dict_lookup_var (default_dict, cnt->n);
- if (!cnt->d)
- cnt->d = force_create_variable (&default_dict, cnt->n, NUMERIC, 0);
+ if (!cnt->d)
+ {
+ cnt->d = dict_create_var (default_dict, cnt->n, 0);
+ assert (cnt->d != NULL);
+ }
}
#if DEBUGGING
static int n_sorted_tab; /* Number of entries in sorted_tab. */
static struct table_entry **sorted_tab; /* Sorted table. */
-/* VARIABLES dictionary. */
-static struct dictionary *var_dict;
+/* Variables specifies on VARIABLES. */
+static struct variable **variables;
+static size_t variables_cnt;
/* TABLES. */
static struct crosstab **xtab;
static struct pool *pl_col; /* For column data. */
static int internal_cmd_crosstabs (void);
-static void free_var_dict (void);
static void precalc (void);
static int calc_general (struct ccase *);
static int calc_integer (struct ccase *);
{
int result = internal_cmd_crosstabs ();
- free_var_dict ();
+ free (variables);
pool_destroy (pl_tc);
pool_destroy (pl_col);
static int
internal_cmd_crosstabs (void)
{
- var_dict = NULL;
+ variables = NULL;
+ variables_cnt = 0;
xtab = NULL;
nxtab = 0;
pl_tc = pool_create ();
return CMD_FAILURE;
#if DEBUGGING
- /* Needs var_dict. */
+ /* Needs variables. */
debug_print ();
#endif
- mode = var_dict ? INTEGER : GENERAL;
- free_var_dict();
+ mode = variables ? INTEGER : GENERAL;
/* CELLS. */
expected = 0;
else
write = CRS_WR_NONE;
- update_weighting (&default_dict);
procedure (precalc, mode == GENERAL ? calc_general : calc_integer, postcalc);
return CMD_SUCCESS;
}
-/* Frees var_dict once it's no longer needed. */
-static void
-free_var_dict (void)
-{
- if (!var_dict)
- return;
-
- {
- int i;
-
- if (var_dict->name_tab)
- {
- hsh_destroy (var_dict->name_tab);
- var_dict->name_tab = NULL;
- }
-
- for (i = 0; i < var_dict->nvar; i++)
- free (var_dict->var[i]);
- free (var_dict->var);
- var_dict->var = NULL;
- var_dict->nvar = 0;
-
- free_dictionary (var_dict);
-
- var_dict = NULL;
- }
-}
-
/* Parses the TABLES subcommand. */
static int
crs_custom_tables (struct cmd_crosstabs *cmd unused)
{
- struct dictionary *dict;
+ struct var_set *var_set;
int n_by;
struct variable ***by = NULL;
int *by_nvar = NULL;
/* Ensure that this is a TABLES subcommand. */
if (!lex_match_id ("TABLES")
- && (token != T_ID || !is_varname (tokid))
+ && (token != T_ID || dict_lookup_var (default_dict, tokid) == NULL)
&& token != T_ALL)
return 2;
lex_match ('=');
- dict = var_dict ? var_dict : &default_dict;
+ if (variables != NULL)
+ var_set = var_set_create_from_array (variables, variables_cnt);
+ else
+ var_set = var_set_create_from_dict (default_dict);
+ assert (var_set != NULL);
for (n_by = 0; ;)
{
by = xrealloc (by, sizeof *by * (n_by + 1));
by_nvar = xrealloc (by_nvar, sizeof *by_nvar * (n_by + 1));
- if (!parse_variables (dict, &by[n_by], &by_nvar[n_by],
- PV_NO_DUPLICATE | PV_NO_SCRATCH))
- goto lossage;
+ if (!parse_var_set_vars (var_set, &by[n_by], &by_nvar[n_by],
+ PV_NO_DUPLICATE | PV_NO_SCRATCH))
+ goto done;
nx *= by_nvar[n_by];
n_by++;
if (n_by < 1)
{
lex_error (_("expecting BY"));
- goto lossage;
+ goto done;
}
else
break;
{
int i;
- if (var_dict == NULL)
- for (i = 0; i < n_by; i++)
- x->v[i] = by[i][by_iter[i]];
- else
- for (i = 0; i < n_by; i++)
- x->v[i] = default_dict.var[by[i][by_iter[i]]->foo];
+ for (i = 0; i < n_by; i++)
+ x->v[i] = by[i][by_iter[i]];
}
{
}
free (by_iter);
}
-
success = 1;
- /* Despite the name, we come here whether we're successful or
- not. */
- lossage:
+
+ done:
+ /* All return paths lead here. */
{
int i;
free (by_nvar);
}
+ var_set_destroy (var_set);
+
return success;
}
static int
crs_custom_variables (struct cmd_crosstabs *cmd unused)
{
- struct variable **v = NULL;
- int nv = 0;
-
if (nxtab)
{
msg (SE, _("VARIABLES must be specified before TABLES."));
for (;;)
{
- int orig_nv = nv;
+ int orig_nv = variables_cnt;
int i;
long min, max;
- if (!parse_variables (&default_dict, &v, &nv,
+ if (!parse_variables (default_dict, &variables, &variables_cnt,
(PV_APPEND | PV_NUMERIC
| PV_NO_DUPLICATE | PV_NO_SCRATCH)))
return 0;
}
lex_get ();
- for (i = orig_nv; i < nv; i++)
+ for (i = orig_nv; i < variables_cnt; i++)
{
- v[i]->p.crs.min = min;
- v[i]->p.crs.max = max + 1.;
- v[i]->p.crs.count = max - min + 1;
+ variables[i]->p.crs.min = min;
+ variables[i]->p.crs.max = max + 1.;
+ variables[i]->p.crs.count = max - min + 1;
}
if (token == '/')
break;
}
- {
- int i;
-
- var_dict = new_dictionary (0);
- var_dict->var = xmalloc (sizeof *var_dict->var * nv);
- var_dict->nvar = nv;
- for (i = 0; i < nv; i++)
- {
- struct variable *var = xmalloc (offsetof (struct variable, width));
- strcpy (var->name, v[i]->name);
- var->index = i;
- var->type = v[i]->type;
- var->foo = v[i]->index;
- var_dict->var[i] = var;
- hsh_force_insert (var_dict->name_tab, var);
- }
-
- free (v);
- return 1;
- }
+ return 1;
lossage:
- free (v);
+ free (variables);
+ variables = NULL;
return 0;
}
{
printf ("CROSSTABS\n");
- if (var_dict)
+ if (variables != NULL)
{
int i;
printf ("\t/VARIABLES=");
- for (i = 0; i < var_dict->nvar; i++)
+ for (i = 0; i < variables_cnt; i++)
{
- struct variable *v = var_dict->var[i];
- struct variable *iv = default_dict.var[v->foo];
+ struct variable *v = variables[i];
printf ("%s ", v->name);
- if (i < var_dict->nvar - 1)
+ if (i < variables_cnt - 1)
{
- struct variable *nv = var_dict->var[i + 1];
- struct variable *niv = default_dict.var[nv->foo];
+ struct variable *nv = variables[i + 1];
- if (iv->p.crs.min == niv->p.crs.min
- && iv->p.crs.max == niv->p.crs.max)
+ if (v->p.crs.min == nv->p.crs.min
+ && v->p.crs.max == nv->p.crs.max)
continue;
}
- printf ("(%d,%d) ", iv->p.crs.min, iv->p.crs.max - 1);
+ printf ("(%d,%d) ", v->p.crs.min, v->p.crs.max - 1);
}
printf ("\n");
}
calc_general (struct ccase *c)
{
/* Case weight. */
- double w = (default_dict.weight_index != -1
- ? c->data[default_dict.var[default_dict.weight_index]->fv].f
- : 1.0);
+ double weight = dict_get_case_weight (default_dict, c);
/* Flattened current table index. */
int t;
|| (cmd.miss == CRS_INCLUDE
&& is_system_missing (&c->data[x->v[j]->fv], x->v[j])))
{
- x->missing += w;
+ x->missing += weight;
goto next_crosstab;
}
{
struct table_entry *tep = pool_alloc (pl_tc, entry_size);
- te->u.freq = w;
+ te->u.freq = weight;
memcpy (tep, te, entry_size);
*tepp = tep;
}
else
- (*tepp)->u.freq += w;
+ (*tepp)->u.freq += weight;
}
next_crosstab:
calc_integer (struct ccase *c)
{
/* Case weight. */
- double w = (default_dict.weight_index != -1
- ? c->data[default_dict.var[default_dict.weight_index]->fv].f
- : 1.0);
+ double weight = dict_get_case_weight (default_dict, c);
/* Flattened current table index. */
int t;
if ((value < v->p.crs.min || value >= v->p.crs.max)
|| (cmd.miss == CRS_TABLE && is_num_user_missing (value, v)))
{
- x->missing += w;
+ x->missing += weight;
goto next_crosstab;
}
const int col = c->data[x->v[COL_VAR]->fv].f - x->v[COL_VAR]->p.crs.min;
const int col_dim = x->v[COL_VAR]->p.crs.count;
- sorted_tab[ofs]->u.data[col + row * col_dim] += w;
+ sorted_tab[ofs]->u.data[col + row * col_dim] += weight;
}
next_crosstab: ;
/* Returns the value of the gamma (factorial) function for an integer
argument X. */
-double
+static double
gamma_int (double x)
{
double r = 1;
+ (sqr (W - sum_fii)
* (W * sum_fijri_ci2 - 4.
* sum_rici * sum_rici)
- / hypercube (W * W - sum_rici))));
+ / pow4 (W * W - sum_rici))));
#else
t[8] = v[8] / ase[8];
#endif
02111-1307, USA. */
#include <config.h>
+#include "data-in.h"
#include <assert.h>
#include <math.h>
#include <ctype.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
-#include "data-in.h"
#include "error.h"
#include "getline.h"
#include "julcal/julcal.h"
#if !data_in_h
#define data_in_h 1
+#include <stddef.h>
#include "format.h"
/* Flags. */
int fc, lc; /* Fixed-format: Column numbers in record. */
struct fmt_spec input; /* Input format of this field. */
int fv; /* First value in case. */
- int type; /* 0=numeric, >0=width of alpha field. */
+ int width; /* 0=numeric, >0=width of alpha field. */
};
/* Constants for DATA LIST type. */
lex_match ('=');
if (!lex_force_id ())
return CMD_FAILURE;
- dls.end = find_variable (tokid);
- if (!dls.end)
- dls.end = force_create_variable (&default_dict, tokid, NUMERIC, 0);
+ dls.end = dict_lookup_var (default_dict, tokid);
+ if (!dls.end)
+ {
+ dls.end = dict_create_var (default_dict, tokid, 0);
+ assert (dls.end != NULL);
+ }
lex_get ();
}
else if (token == T_ID)
for (i = 0; i < fx.nname; i++)
{
int type;
+ int width;
struct variable *v;
- if (fx.spec.input.type == FMT_A || fx.spec.input.type == FMT_AHEX)
- type = ALPHA;
- else
- type = NUMERIC;
-
- v = create_variable (&default_dict, fx.name[i], type, dividend);
+ if (fx.spec.input.type == FMT_A || fx.spec.input.type == FMT_AHEX)
+ {
+ type = ALPHA;
+ width = dividend;
+ }
+ else
+ {
+ type = NUMERIC;
+ width = 0;
+ }
+
+ v = dict_create_var (default_dict, fx.name[i], width);
if (v)
{
convert_fmt_ItoO (&fx.spec.input, &v->print);
}
else
{
- v = find_variable (fx.name[i]);
- assert (v);
+ v = dict_lookup_var (default_dict, fx.name[i]);
+ assert (v != NULL);
if (!vfm_source)
{
msg (SE, _("%s is a duplicate variable name."), fx.name[i]);
fx.spec.fc = fx.fc + dividend * i;
fx.spec.lc = fx.spec.fc + dividend - 1;
fx.spec.fv = v->fv;
- fx.spec.type = v->type == NUMERIC ? 0 : v->width;
+ fx.spec.width = v->width;
append_var_spec (&fx.spec);
}
return 1;
else
{
int type;
+ int width;
struct variable *v;
- type = (formats[f->f.type].cat & FCAT_STRING) ? ALPHA : NUMERIC;
+ if (formats[f->f.type].cat & FCAT_STRING)
+ {
+ type = ALPHA;
+ width = f->f.w;
+ }
+ else
+ {
+ type = NUMERIC;
+ width = 0;
+ }
if (fx.cname >= fx.nname)
{
msg (SE, _("The number of format "
return 0;
}
- fx.spec.v = v = create_variable (&default_dict,
+ fx.spec.v = v = dict_create_var (default_dict,
fx.name[fx.cname++],
- type, f->f.w);
+ width);
if (!v)
{
msg (SE, _("%s is a duplicate variable name."), fx.name[i]);
fx.spec.fc = fx.sc;
fx.spec.lc = fx.sc + f->f.w - 1;
fx.spec.fv = v->fv;
- fx.spec.type = v->type == NUMERIC ? 0 : v->width;
+ fx.spec.width = v->width;
append_var_spec (&fx.spec);
fx.sc += f->f.w;
char **name;
int nname;
int i;
- int type;
lex_get ();
while (token != '.')
{
+ int width;
+
if (!parse_DATA_LIST_vars (&name, &nname, PV_NONE))
return 0;
if (lex_match ('('))
spec.input = in;
if (in.type == FMT_A || in.type == FMT_AHEX)
- type = ALPHA;
+ width = in.w;
else
- type = NUMERIC;
+ width = 0;
for (i = 0; i < nname; i++)
{
struct variable *v;
- spec.v = v = create_variable (&default_dict, name[i], type, in.w);
+ spec.v = v = dict_create_var (default_dict, name[i], width);
if (!v)
{
msg (SE, _("%s is a duplicate variable name."), name[i]);
strcpy (spec.name, name[i]);
spec.fv = v->fv;
- spec.type = type == NUMERIC ? 0 : v->width;
+ spec.width = width;
append_var_spec (&spec);
}
for (i = 0; i < nname; i++)
"or blanks, as appropriate."),
var_spec->name);
for (; var_spec; var_spec = var_spec->next)
- if (!var_spec->type)
+ if (var_spec->width == 0)
temp_case->data[var_spec->fv].f = SYSMIS;
else
- memset (temp_case->data[var_spec->fv].s, ' ', var_spec->type);
+ memset (temp_case->data[var_spec->fv].s, ' ', var_spec->width);
break;
}
}
/* Data pass! */
- update_weighting (&default_dict);
bad_weight = 0;
procedure (precalc, calc, postcalc);
dsc_custom_variables (struct cmd_descriptives *cmd unused)
{
if (!lex_match_id ("VARIABLES")
- && (token != T_ID || !is_varname (tokid))
+ && (token != T_ID || dict_lookup_var (default_dict, tokid) == NULL)
&& token != T_ALL)
return 2;
lex_match ('=');
int i, n;
n = n_variables;
- if (!parse_variables (NULL, &v_variables, &n_variables,
+ if (!parse_variables (default_dict, &v_variables, &n_variables,
PV_DUPLICATE | PV_SINGLE | PV_APPEND | PV_NUMERIC
| PV_NO_SCRATCH))
return 0;
msg (SE, _("Name for z-score variable expected."));
return 0;
}
- if (is_varname (tokid))
+ if (dict_lookup_var (default_dict, tokid))
{
msg (SE, _("Z-score variable name `%s' is a "
"duplicate variable name with a current variable."),
{
int i;
- if (is_varname (name))
+ if (dict_lookup_var (default_dict, name) != NULL)
return 0;
for (i = 0; i < n_variables; i++)
{
struct variable *d;
t->z[count].s = v;
- t->z[count].d = d = force_create_variable (&default_dict,
- v->p.dsc.zname,
- NUMERIC, 0);
+ t->z[count].d = d = dict_create_var (default_dict,
+ v->p.dsc.zname, 0);
+ assert (d != NULL);
if (v->label)
{
d->label = xmalloc (strlen (v->label) + 12);
static int case_id;
/* Get the weight for this case. */
- double w;
+ double weight = dict_get_case_weight (default_dict, c);
- if (default_dict.weight_index == -1)
- w = 1.0;
- else
+ if (weight <= 0.0)
{
- w = c->data[default_dict.weight_index].f;
- if (w <= 0.0 || w == SYSMIS)
- {
- w = 0.0;
- bad_weight = 1;
- }
+ weight = 0.0;
+ bad_weight = 1;
}
-
case_id++;
/* Handle missing values. */
{
if (opt[op_excl_miss])
{
- d_glob_missing += w;
+ d_glob_missing += weight;
return 1;
}
else
{
- d_glob_miss_list += w;
+ d_glob_miss_list += weight;
goto iterate;
}
}
}
- d_glob_valid += w;
+ d_glob_valid += weight;
iterate:
for (i = 0; i < n_variables; i++)
if (X == SYSMIS
|| (!opt[op_incl_miss] && is_num_user_missing (X, v_variables[i])))
{
- inf->miss += w;
+ inf->miss += weight;
continue;
}
I am happy that mathematical formulas may not be
copyrighted. */
W_old = inf->valid;
- W_new = inf->valid += w;
- v = (w / W_new) * (X - inf->X_bar);
+ W_new = inf->valid += weight;
+ v = (weight / W_new) * (X - inf->X_bar);
v2 = v * v;
v3 = v2 * v;
v4 = v3 * v;
- w2 = w * w;
- w3 = w2 * w;
- w4 = w3 * w;
+ w2 = weight * weight;
+ w3 = w2 * weight;
+ w4 = w3 * weight;
inf->M4 += (-4.0 * v * inf->M3 + 6.0 * v2 * inf->M2
- + (W_new * W_new - 3 * w * W_old / w3) * v4 * W_old * W_new);
+ + (W_new * W_new - 3 * weight * W_old / w3) * v4 * W_old * W_new);
inf->M3 += (-3.0 * v * inf->M2 + W_new * W_old / w2
- * (W_new - 2 * w) * v3);
- inf->M2 += W_new * W_old / w * v2;
+ * (W_new - 2 * weight) * v3);
+ inf->M2 += W_new * W_old / weight * v2;
inf->X_bar += v;
if (X < inf->min)
inf->min = X;
#endif
#include <assert.h>
+#include "dfm.h"
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
char *
dfm_get_record (struct file_handle *h, int *len)
{
+ assert (h != NULL);
+
if (h->class == NULL)
{
if (!open_file_r (h))
than system files). dfm is an fhuser, so see file-handle.h for the
fhuser interface. */
+#include <stddef.h>
+
/* I/O utilities. */
struct file_handle;
char *dfm_get_record (struct file_handle *handle, int *len);
--- /dev/null
+/* PSPP - computes sample statistics.
+ Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Written by Ben Pfaff <blp@gnu.org>.
+
+ 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 the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#include <config.h>
+#include <assert.h>
+#include <stdlib.h>
+#include "algorithm.h"
+#include "alloc.h"
+#include "hash.h"
+#include "misc.h"
+#include "str.h"
+#include "value-labels.h"
+#include "var.h"
+
+/* A dictionary. */
+struct dictionary
+ {
+ struct variable **var; /* Variables. */
+ size_t var_cnt, var_cap; /* Number of variables, capacity. */
+ struct hsh_table *name_tab; /* Variable index by name. */
+ int value_cnt; /* Number of `union value's per case. */
+ struct variable **split; /* SPLIT FILE vars. */
+ size_t split_cnt; /* SPLIT FILE count. */
+ struct variable *weight; /* WEIGHT variable. */
+ struct variable *filter; /* FILTER variable. */
+ int case_limit; /* Current case limit (N command). */
+ char *label; /* File label. */
+ char *documents; /* Documents, as a string. */
+ struct vector **vector; /* Vectors of variables. */
+ size_t vector_cnt; /* Number of vectors. */
+ };
+
+struct dictionary *
+dict_create (void)
+{
+ struct dictionary *d = xmalloc (sizeof *d);
+
+ d->var = NULL;
+ d->var_cnt = d->var_cap = 0;
+ d->name_tab = hsh_create (8, compare_variables, hash_variable, NULL, NULL);
+ d->value_cnt = 0;
+ d->split = NULL;
+ d->split_cnt = 0;
+ d->weight = NULL;
+ d->filter = NULL;
+ d->case_limit = 0;
+ d->label = NULL;
+ d->documents = NULL;
+ d->vector = NULL;
+ d->vector_cnt = 0;
+
+ return d;
+}
+
+struct dictionary *
+dict_clone (const struct dictionary *s)
+{
+ struct dictionary *d;
+ size_t i;
+
+ assert (s != NULL);
+
+ d = dict_create ();
+ for (i = 0; i < s->var_cnt; i++)
+ dict_clone_var (d, s->var[i], s->var[i]->name);
+ d->value_cnt = s->value_cnt;
+
+ d->split_cnt = s->split_cnt;
+ if (d->split_cnt > 0)
+ {
+ d->split = xmalloc (d->split_cnt * sizeof *d->split);
+ for (i = 0; i < d->split_cnt; i++)
+ {
+ d->split[i] = dict_lookup_var (d, s->split[i]->name);
+ assert (d->split[i] != NULL);
+ }
+ }
+
+ if (s->weight != NULL)
+ {
+ d->weight = dict_lookup_var (d, s->weight->name);
+ assert (d->weight != NULL);
+ }
+
+ if (s->filter != NULL)
+ {
+ d->filter = dict_lookup_var (d, s->filter->name);
+ assert (d->filter != NULL);
+ }
+
+ d->case_limit = s->case_limit;
+ dict_set_label (d, dict_get_label (s));
+ dict_set_documents (d, dict_get_documents (s));
+
+ for (i = 0; i < s->vector_cnt; i++)
+ dict_create_vector (d, s->vector[i]->name,
+ s->vector[i]->var, s->vector[i]->cnt);
+
+ return d;
+}
+
+void
+dict_clear (struct dictionary *d)
+{
+ /* FIXME? Should we really clear case_limit, label, documents?
+ Others are necessarily cleared by deleting all the variables.*/
+ int i;
+
+ assert (d != NULL);
+
+ for (i = 0; i < d->var_cnt; i++)
+ {
+ struct variable *v = d->var[i];
+ val_labs_destroy (v->val_labs);
+ free (v->label);
+ free (v);
+ }
+ free (d->var);
+ d->var = NULL;
+ d->var_cnt = d->var_cap = 0;
+ hsh_clear (d->name_tab);
+ d->value_cnt = 0;
+ free (d->split);
+ d->split = NULL;
+ d->split_cnt = 0;
+ d->weight = NULL;
+ d->filter = NULL;
+ d->case_limit = 0;
+ free (d->label);
+ d->label = NULL;
+ free (d->documents);
+ d->documents = NULL;
+ dict_clear_vectors (d);
+}
+
+void
+dict_destroy (struct dictionary *d)
+{
+ if (d != NULL)
+ {
+ dict_clear (d);
+ hsh_destroy (d->name_tab);
+ free (d);
+ }
+}
+
+size_t
+dict_get_var_cnt (const struct dictionary *d)
+{
+ assert (d != NULL);
+
+ return d->var_cnt;
+}
+
+struct variable *
+dict_get_var (const struct dictionary *d, size_t idx)
+{
+ assert (d != NULL);
+ assert (idx < d->var_cnt);
+
+ return d->var[idx];
+}
+
+void
+dict_get_vars (const struct dictionary *d, struct variable ***vars,
+ size_t *cnt, unsigned exclude_classes)
+{
+ size_t count;
+ size_t i;
+
+ assert (d != NULL);
+ assert (vars != NULL);
+ assert (cnt != NULL);
+ assert ((exclude_classes & ~((1u << DC_ORDINARY)
+ | (1u << DC_SYSTEM)
+ | (1u << DC_SCRATCH))) == 0);
+
+ count = 0;
+ for (i = 0; i < d->var_cnt; i++)
+ if (!(exclude_classes & (1u << dict_class_from_id (d->var[i]->name))))
+ count++;
+
+ *vars = xmalloc (count * sizeof **vars);
+ *cnt = 0;
+ for (i = 0; i < d->var_cnt; i++)
+ if (!(exclude_classes & (1u << dict_class_from_id (d->var[i]->name))))
+ (*vars)[(*cnt)++] = d->var[i];
+ assert (*cnt == count);
+}
+
+struct variable *
+dict_create_var (struct dictionary *d, const char *name, int width)
+{
+ struct variable *v;
+
+ assert (d != NULL);
+ assert (name != NULL);
+ assert (strlen (name) >= 1 && strlen (name) <= 8);
+ assert (width >= 0 && width < 256);
+
+ /* Make sure there's not already a variable by that name. */
+ if (dict_lookup_var (d, name) != NULL)
+ return NULL;
+
+ /* Allocate and initialize variable. */
+ v = xmalloc (sizeof *v);
+ strncpy (v->name, name, sizeof v->name);
+ v->name[8] = '\0';
+ v->index = d->var_cnt;
+ v->type = width == 0 ? NUMERIC : ALPHA;
+ v->width = width;
+ v->fv = d->value_cnt;
+ v->nv = width == 0 ? 1 : DIV_RND_UP (width, 8);
+ v->left = name[0] == '#';
+ v->miss_type = MISSING_NONE;
+ if (v->type == NUMERIC)
+ {
+ v->print.type = FMT_F;
+ v->print.w = 8;
+ v->print.d = 2;
+ }
+ else
+ {
+ v->print.type = FMT_A;
+ v->print.w = v->width;
+ v->print.d = 0;
+ }
+ v->val_labs = val_labs_create (v->width);
+ v->label = NULL;
+
+ /* Update dictionary. */
+ if (d->var_cnt >= d->var_cap)
+ {
+ d->var_cap = 8 + 2 * d->var_cap;
+ d->var = xrealloc (d->var, d->var_cap * sizeof *d->var);
+ }
+ d->var[v->index] = v;
+ d->var_cnt++;
+ hsh_force_insert (d->name_tab, v);
+ d->value_cnt += v->nv;
+
+ return v;
+}
+
+struct variable *
+dict_clone_var (struct dictionary *d, const struct variable *ov,
+ const char *name)
+{
+ struct variable *nv;
+
+ assert (d != NULL);
+ assert (ov != NULL);
+ assert (name != NULL);
+ assert (strlen (name) >= 1 && strlen (name) <= 8);
+
+ nv = dict_create_var (d, name, ov->width);
+ if (nv == NULL)
+ return NULL;
+
+ nv->left = ov->left;
+ nv->miss_type = ov->miss_type;
+ memcpy (nv->missing, ov->missing, sizeof nv->missing);
+ nv->print = ov->print;
+ nv->write = ov->write;
+ val_labs_destroy (nv->val_labs);
+ nv->val_labs = val_labs_copy (ov->val_labs);
+ if (ov->label != NULL)
+ nv->label = xstrdup (ov->label);
+
+ return nv;
+}
+
+void
+dict_rename_var (struct dictionary *d, struct variable *v,
+ const char *new_name)
+{
+ assert (d != NULL);
+ assert (v != NULL);
+ assert (new_name != NULL);
+ assert (strlen (new_name) >= 1 && strlen (new_name) <= 8);
+
+ if (!strcmp (v->name, new_name))
+ return;
+
+ assert (dict_lookup_var (d, new_name) == NULL);
+
+ hsh_force_delete (d->name_tab, v);
+ strncpy (v->name, new_name, sizeof v->name);
+ v->name[8] = '\0';
+ hsh_force_insert (d->name_tab, v);
+}
+
+struct variable *
+dict_lookup_var (const struct dictionary *d, const char *name)
+{
+ struct variable v;
+
+ assert (d != NULL);
+ assert (name != NULL);
+ assert (strlen (name) >= 1 && strlen (name) <= 8);
+
+ strncpy (v.name, name, sizeof v.name);
+ v.name[8] = '\0';
+
+ return hsh_find (d->name_tab, &v);
+}
+
+int
+dict_contains_var (const struct dictionary *d, const struct variable *v)
+{
+ assert (d != NULL);
+ assert (v != NULL);
+
+ return dict_lookup_var (d, v->name) == v;
+}
+
+static int
+compare_variable_dblptrs (const void *a_, const void *b_, void *aux unused)
+{
+ struct variable *const *a = a_;
+ struct variable *const *b = b_;
+
+ if (a > b)
+ return 1;
+ else if (a < b)
+ return -1;
+ else
+ return 0;
+}
+
+void
+dict_delete_var (struct dictionary *d, struct variable *v)
+{
+ size_t i;
+
+ /* FIXME? Does not sync d->value_cnt. */
+ assert (d != NULL);
+ assert (v != NULL);
+ assert (dict_contains_var (d, v));
+ assert (d->var[v->index] == v);
+
+ /* Remove v from splits, weight, filter variables. */
+ d->split_cnt = remove_equal (d->split, d->split_cnt, sizeof *d->split,
+ &v,
+ compare_variable_dblptrs, NULL);
+ if (d->weight == v)
+ d->weight = NULL;
+ if (d->filter == v)
+ d->filter = NULL;
+ dict_clear_vectors (d);
+
+ /* Remove v from var array. */
+ d->var_cnt--;
+ memmove (d->var + v->index, d->var + v->index + 1,
+ (d->var_cnt - v->index) * sizeof *d->var);
+
+ /* Update index. */
+ for (i = v->index; i < d->var_cnt; i++)
+ d->var[i]->index = i;
+
+ /* Update name hash. */
+ hsh_force_delete (d->name_tab, v);
+
+ /* Free memory. */
+ val_labs_destroy (v->val_labs);
+ free (v->label);
+ free (v);
+
+}
+
+void
+dict_delete_vars (struct dictionary *d,
+ struct variable *const *vars, size_t count)
+{
+ /* FIXME: this can be done in O(count) time, but this algorithm
+ is O(count**2). */
+ assert (d != NULL);
+ assert (count == 0 || vars != NULL);
+
+ while (count-- > 0)
+ dict_delete_var (d, *vars++);
+}
+
+void
+dict_reorder_vars (struct dictionary *d,
+ struct variable *const *order, size_t count)
+{
+ struct variable **new_var;
+ size_t i;
+
+ assert (d != NULL);
+ assert (count == 0 || order != NULL);
+ assert (count <= d->var_cnt);
+
+ new_var = xmalloc (d->var_cnt * sizeof *new_var);
+ memcpy (new_var, order, count * sizeof *new_var);
+ for (i = 0; i < count; i++)
+ {
+ assert (d->var[order[i]->index] != NULL);
+ d->var[order[i]->index] = NULL;
+ order[i]->index = i;
+ }
+ for (i = 0; i < d->var_cnt; i++)
+ if (d->var[i] != NULL)
+ {
+ assert (count < d->var_cnt);
+ new_var[count] = d->var[i];
+ new_var[count]->index = count;
+ count++;
+ }
+ free (d->var);
+ d->var = new_var;
+}
+
+int
+dict_rename_vars (struct dictionary *d,
+ struct variable **vars, char **new_names,
+ size_t count, char **err_name)
+{
+ char **old_names;
+ size_t i;
+ int success = 1;
+
+ assert (d != NULL);
+ assert (count == 0 || vars != NULL);
+ assert (count == 0 || new_names != NULL);
+
+ old_names = xmalloc (count * sizeof *old_names);
+ for (i = 0; i < count; i++)
+ {
+ assert (d->var[vars[i]->index] == vars[i]);
+ hsh_force_delete (d->name_tab, vars[i]);
+ old_names[i] = xstrdup (vars[i]->name);
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ assert (new_names[i] != NULL);
+ assert (strlen (new_names[i]) < 9);
+ strcpy (vars[i]->name, new_names[i]);
+ if (hsh_insert (d->name_tab, vars[i]) != NULL)
+ {
+ size_t fail_idx = i;
+ if (err_name != NULL)
+ *err_name = new_names[i];
+
+ for (i = 0; i < fail_idx; i++)
+ hsh_force_delete (d->name_tab, vars[i]);
+
+ for (i = 0; i < count; i++)
+ {
+ strcpy (vars[i]->name, old_names[i]);
+ hsh_force_insert (d->name_tab, vars[i]);
+ }
+
+ success = 0;
+ break;
+ }
+ }
+
+ for (i = 0; i < count; i++)
+ free (old_names[i]);
+ free (old_names);
+
+ return success;
+}
+
+struct variable *
+dict_get_weight (const struct dictionary *d)
+{
+ assert (d != NULL);
+ assert (d->weight == NULL || dict_contains_var (d, d->weight));
+
+ return d->weight;
+}
+
+double
+dict_get_case_weight (const struct dictionary *d, const struct ccase *c)
+{
+ assert (d != NULL);
+ assert (c != NULL);
+
+ if (d->weight == NULL)
+ return 1.0;
+ else
+ {
+ double w = c->data[d->weight->fv].f;
+ if (w < 0.0)
+ w = 0.0;
+ return w;
+ }
+}
+
+void
+dict_set_weight (struct dictionary *d, struct variable *v)
+{
+ assert (d != NULL);
+ assert (v == NULL || dict_contains_var (d, v));
+ assert (v == NULL || v->type == NUMERIC);
+
+ d->weight = v;
+}
+
+struct variable *
+dict_get_filter (const struct dictionary *d)
+{
+ assert (d != NULL);
+ assert (d->filter == NULL || dict_contains_var (d, d->filter));
+
+ return d->filter;
+}
+
+void
+dict_set_filter (struct dictionary *d, struct variable *v)
+{
+ assert (d != NULL);
+ assert (v == NULL || dict_contains_var (d, v));
+
+ d->filter = v;
+}
+
+int
+dict_get_case_limit (const struct dictionary *d)
+{
+ assert (d != NULL);
+
+ return d->case_limit;
+}
+
+void
+dict_set_case_limit (struct dictionary *d, int case_limit)
+{
+ assert (d != NULL);
+ assert (case_limit >= 0);
+
+ d->case_limit = case_limit;
+}
+
+int
+dict_get_value_cnt (const struct dictionary *d)
+{
+ assert (d != NULL);
+
+ return d->value_cnt;
+}
+
+void
+dict_compact_values (struct dictionary *d)
+{
+ size_t i;
+
+ d->value_cnt = 0;
+ for (i = 0; i < d->var_cnt; i++)
+ {
+ struct variable *v = d->var[i];
+
+ v->fv = d->value_cnt;
+ d->value_cnt += v->nv;
+ }
+}
+
+struct variable *const *
+dict_get_split_vars (const struct dictionary *d)
+{
+ assert (d != NULL);
+
+ return d->split;
+}
+
+size_t
+dict_get_split_cnt (const struct dictionary *d)
+{
+ assert (d != NULL);
+
+ return d->split_cnt;
+}
+
+void
+dict_set_split_vars (struct dictionary *d,
+ struct variable *const *split, size_t cnt)
+{
+ assert (d != NULL);
+ assert (cnt == 0 || split != NULL);
+
+ d->split_cnt = cnt;
+ d->split = xrealloc (d->split, cnt * sizeof *d->split);
+ memcpy (d->split, split, cnt * sizeof *d->split);
+}
+
+const char *
+dict_get_label (const struct dictionary *d)
+{
+ assert (d != NULL);
+
+ return d->label;
+}
+
+void
+dict_set_label (struct dictionary *d, const char *label)
+{
+ assert (d != NULL);
+
+ free (d->label);
+ if (label == NULL)
+ d->label = NULL;
+ else if (strlen (label) < 60)
+ d->label = xstrdup (label);
+ else
+ {
+ d->label = xmalloc (61);
+ memcpy (d->label, label, 60);
+ d->label[60] = '\0';
+ }
+}
+
+const char *
+dict_get_documents (const struct dictionary *d)
+{
+ assert (d != NULL);
+
+ return d->documents;
+}
+
+void
+dict_set_documents (struct dictionary *d, const char *documents)
+{
+ assert (d != NULL);
+
+ free (d->documents);
+ if (documents == NULL)
+ d->documents = NULL;
+ else
+ d->documents = xstrdup (documents);
+}
+
+int
+dict_create_vector (struct dictionary *d,
+ const char *name,
+ struct variable **var, size_t cnt)
+{
+ struct vector *vector;
+
+ assert (d != NULL);
+ assert (name != NULL);
+ assert (strlen (name) > 0 && strlen (name) < 9);
+ assert (var != NULL);
+ assert (cnt > 0);
+
+ if (dict_lookup_vector (d, name) != NULL)
+ return 0;
+
+ d->vector = xrealloc (d->vector, (d->vector_cnt + 1) * sizeof *d->vector);
+ vector = d->vector[d->vector_cnt] = xmalloc (sizeof *vector);
+ vector->idx = d->vector_cnt++;
+ strncpy (vector->name, name, 8);
+ vector->name[8] = '\0';
+ vector->var = xmalloc (cnt * sizeof *var);
+ memcpy (vector->var, var, cnt * sizeof *var);
+ vector->cnt = cnt;
+
+ return 1;
+}
+
+const struct vector *
+dict_get_vector (const struct dictionary *d, size_t idx)
+{
+ assert (d != NULL);
+ assert (idx < d->vector_cnt);
+
+ return d->vector[idx];
+}
+
+size_t
+dict_get_vector_cnt (const struct dictionary *d)
+{
+ assert (d != NULL);
+
+ return d->vector_cnt;
+}
+
+const struct vector *
+dict_lookup_vector (const struct dictionary *d, const char *name)
+{
+ size_t i;
+
+ assert (d != NULL);
+ assert (name != NULL);
+
+ for (i = 0; i < d->vector_cnt; i++)
+ if (!strcmp (d->vector[i]->name, name))
+ return d->vector[i];
+ return NULL;
+}
+
+void
+dict_clear_vectors (struct dictionary *d)
+{
+ size_t i;
+
+ assert (d != NULL);
+
+ for (i = 0; i < d->vector_cnt; i++)
+ {
+ free (d->vector[i]->var);
+ free (d->vector[i]);
+ }
+ free (d->vector);
+ d->vector = NULL;
+ d->vector_cnt = 0;
+}
02111-1307, USA. */
#include <config.h>
+#include "do-ifP.h"
#include <assert.h>
#include <stdlib.h>
#include "alloc.h"
*/
/* *INDENT-ON* */
-#include "do-ifP.h"
-
static struct do_if_trns *parse_do_if (void);
static void add_ELSE_IF (struct do_if_trns *);
static int goto_trns_proc (struct trns_header *, struct ccase *);
#endif
#include <assert.h>
+#include "error.h"
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "alloc.h"
#include "command.h"
-#include "error.h"
#include "getline.h"
#include "main.h"
#include "output.h"
#endif
#include <ctype.h>
+#include "expr.h"
+#include "exprP.h"
#include <assert.h>
#include <math.h>
#include <errno.h>
#include "approx.h"
#include "data-in.h"
#include "error.h"
-#include "expr.h"
-#include "exprP.h"
#include "julcal/julcal.h"
#include "magic.h"
#include "random.h"
#include "stats.h"
#include "str.h"
#include "var.h"
-#include "vector.h"
#include "vfm.h"
#include "vfmP.h"
case OP_VEC_ELEM_NUM:
{
int rindx = sp[0].f + EPSILON;
- struct vector *v = &vec[*op++];
+ const struct vector *v = dict_get_vector (default_dict, *op++);
- if (sp[0].f == SYSMIS || rindx < 1 || rindx > v->nv)
+ if (sp[0].f == SYSMIS || rindx < 1 || rindx > v->cnt)
{
if (sp[0].f == SYSMIS)
msg (SE, _("SYSMIS is not a valid index value for vector "
sp->f = SYSMIS;
break;
}
- sp->f = c->data[v->v[rindx - 1]->fv].f;
+ sp->f = c->data[v->var[rindx - 1]->fv].f;
}
break;
case OP_VEC_ELEM_STR:
{
int rindx = sp[0].f + EPSILON;
- struct vector *vect = &vec[*op++];
+ const struct vector *vect = dict_get_vector (default_dict, *op++);
struct variable *v;
- if (sp[0].f == SYSMIS || rindx < 1 || rindx > vect->nv)
+ if (sp[0].f == SYSMIS || rindx < 1 || rindx > vect->cnt)
{
if (sp[0].f == SYSMIS)
msg (SE, _("SYSMIS is not a valid index value for vector "
break;
}
- v = vect->v[rindx - 1];
+ v = vect->var[rindx - 1];
CHECK_STRING_SPACE (v->width);
sp->c = ALLOC_STRING_SPACE (v->width);
sp->c[0] = v->width;
02111-1307, USA. */
#include <config.h>
+#include "expr.h"
+#include "exprP.h"
#include <assert.h>
#include <math.h>
#include <ctype.h>
#include "approx.h"
#include "data-in.h"
#include "error.h"
-#include "expr.h"
-#include "exprP.h"
#include "julcal/julcal.h"
#include "misc.h"
#include "stats.h"
max_height = height;
}
- /* ANSI says we have to waste space for one `value' since pointers
- are not guaranteed to be able to point to a spot *before* a
- block. If only all the world were a VAX... */
+ /* We waste space for one `value' since pointers are not
+ guaranteed to be able to point to a spot before a block. */
max_height++;
e->stack = xmalloc (max_height * sizeof *e->stack);
02111-1307, USA. */
#include <config.h>
+#include "expr.h"
+#include "exprP.h"
#include <assert.h>
#include <ctype.h>
#include <float.h>
#include "algorithm.h"
#include "alloc.h"
#include "error.h"
-#include "expr.h"
-#include "exprP.h"
#include "lexer.h"
#include "misc.h"
#include "str.h"
#include "var.h"
-#include "vector.h"
#include "vfm.h"
\f
/* Declarations. */
}
/* Otherwise, it must be a user variable. */
- v = find_variable (tokid);
+ v = dict_lookup_var (default_dict, tokid);
lex_get ();
if (v == NULL)
{
static int
MISSING_func (struct function * f, int x unused, union any_node ** n)
{
- if (token == T_ID && is_varname (tokid) && lex_look_ahead () == ')')
+ if (token == T_ID
+ && dict_lookup_var (default_dict, tokid) != NULL
+ && lex_look_ahead () == ')')
{
struct var_node *c = xmalloc (sizeof *c);
c->v = parse_variable ();
{
int t;
- if (token == T_ID && is_varname (tokid) && lex_look_ahead () == ')')
+ if (token == T_ID
+ && dict_lookup_var (default_dict, tokid)
+ && lex_look_ahead () == ')')
{
struct variable *v;
v = parse_variable ();
/* FIXME: Is this condition failsafe? Can we _ever_ have two
juxtaposed identifiers otherwise? */
- if (token == T_ID && is_varname (tokid)
+ if (token == T_ID && dict_lookup_var (default_dict, tokid) != NULL
&& toupper (lex_look_ahead ()) == 'T')
{
struct variable **v;
opts |= PV_NUMERIC;
else if (type == ALPHA)
opts |= PV_STRING;
- if (!parse_variables (NULL, &v, &nv, opts))
+ if (!parse_variables (default_dict, &v, &nv, opts))
goto fail;
if (nv + (*n)->nonterm.n >= m)
{
char fname[32], *cp;
int t;
int min_args;
- struct vector *v;
+ const struct vector *v;
/* Check for a vector with this name. */
- v = find_vector (tokid);
+ v = dict_lookup_vector (default_dict, tokid);
if (v)
{
lex_get ();
*n = xmalloc (sizeof (struct nonterm_node)
+ sizeof (union any_node *[2]));
- (*n)->nonterm.type = (v->v[0]->type == NUMERIC
+ (*n)->nonterm.type = (v->var[0]->type == NUMERIC
? OP_VEC_ELEM_NUM : OP_VEC_ELEM_STR);
(*n)->nonterm.n = 0;
msg (SE, _("`)' expected after a vector index value."));
goto fail;
}
- ((*n)->nonterm.arg[1]) = (union any_node *) v->index;
+ ((*n)->nonterm.arg[1]) = (union any_node *) v->idx;
- return v->v[0]->type == NUMERIC ? EX_NUMERIC : EX_STRING;
+ return v->var[0]->type == NUMERIC ? EX_NUMERIC : EX_STRING;
}
ds_truncate (&tokstr, 31);
file entered via BEGIN DATA/END DATA. */
extern struct file_handle *inline_file;
+/* Initialization. */
+void fh_init_files (void);
+
/* Opening and closing handles. */
struct file_handle *fh_get_handle_by_name (const char name[9]);
struct file_handle *fh_get_handle_by_filename (const char *filename);
02111-1307, USA. */
#include <config.h>
+#include "file-handle.h"
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include "alloc.h"
#include "filename.h"
-#include "file-handle.h"
#include "command.h"
#include "hash.h"
#include "lexer.h"
static void
create_col_var (struct col_spec *c)
{
- int type;
int width;
- type = (formats[c->fmt].cat & FCAT_STRING) ? ALPHA : NUMERIC;
- if (type == ALPHA)
+ if (formats[c->fmt].cat & FCAT_STRING)
width = c->nc;
else
width = 0;
- c->v = force_create_variable (&default_dict, c->name, type, width);
+ c->v = dict_create_var (default_dict, c->name, width);
}
/* Parses variable, column, type specifications for a variable. */
#endif
#include <assert.h>
+#include "filename.h"
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include "alloc.h"
#include "error.h"
-#include "filename.h"
#include "settings.h"
#include "str.h"
#include "version.h"
if (lex_match_id ("VARIABLES"))
{
lex_match ('=');
- if (!parse_variables (&default_dict, &var, &nvar, PV_NO_DUPLICATE))
+ if (!parse_variables (default_dict, &var, &nvar, PV_NO_DUPLICATE))
return CMD_FAILURE;
lex_match ('/');
}
else
- fill_all_vars (&var, &nvar, FV_NO_SYSTEM);
+ dict_get_vars (default_dict, &var, &nvar, 1u << DC_SYSTEM);
lex_match ('/');
if (lex_match_id ("NEWNAMES"))
}
}
else
- newnames = find_variable ("CASE_LBL");
+ newnames = dict_lookup_var (default_dict, "CASE_LBL");
if (newnames)
{
new_names_tail = NULL;
procedure (NULL, NULL, NULL);
- clear_default_dict ();
+ dict_clear (default_dict);
if (!build_dictionary ())
{
discard_variables ();
*cp = 0;
}
- if (create_variable (&default_dict, name, NUMERIC, 0))
+ if (dict_create_var (default_dict, name, 0))
return 1;
/* Add numeric extensions until acceptable. */
memcpy (n, name, ofs);
sprintf (&n[ofs], "%d", i);
- if (create_variable (&default_dict, n, NUMERIC, 0))
+ if (dict_create_var (default_dict, n, 0))
return 1;
}
}
static int
build_dictionary (void)
{
- force_create_variable (&default_dict, "CASE_LBL", ALPHA, 8);
+ if (!dict_create_var (default_dict, "CASE_LBL", 8))
+ assert (0);
if (!new_names_tail)
{
for (i = 0; i < case_count; i++)
{
+ struct variable *v;
char s[9];
sprintf (s, "VAR%03d", i);
- force_create_variable (&default_dict, s, NUMERIC, 0);
+ v = dict_create_var (default_dict, s, 0);
+ assert (v != NULL);
}
}
else
02111-1307, USA. */
#include <config.h>
-
+#include "format.h"
#include <ctype.h>
#include <assert.h>
#include <stdlib.h>
#include "error.h"
-#include "format.h"
#include "lexer.h"
#include "misc.h"
#include "str.h"
if (token == '.')
break;
- if (!parse_variables (NULL, &v, &cv, PV_SAME_TYPE))
+ if (!parse_variables (default_dict, &v, &cv, PV_SAME_TYPE))
return CMD_PART_SUCCESS_MAYBE;
type = v[0]->type;
n_variables = 0;
v_variables = NULL;
- for (i = 0; i < default_dict.nvar; i++)
- default_dict.var[i]->foo = 0;
+ for (i = 0; i < dict_get_var_cnt (default_dict); i++)
+ dict_get_var(default_dict, i)->p.frq.used = 0;
lex_match_id ("FREQUENCIES");
if (!parse_frequencies (&cmd))
cmd.sort = FRQ_AVALUE;
/* Do it! */
- update_weighting (&default_dict);
procedure (precalc, calc, postcalc);
return CMD_SUCCESS;
double weight;
int i;
- if (default_dict.weight_index == -1)
- weight = 1.0;
- else
- weight = c->data[default_dict.var[default_dict.weight_index]->fv].f;
+ weight = dict_get_case_weight (default_dict, c);
for (i = 0; i < n_variables; i++)
{
int i;
lex_match ('=');
- if (token != T_ALL && (token != T_ID || !is_varname (tokid)))
+ if (token != T_ALL && (token != T_ID
+ || dict_lookup_var (default_dict, tokid) == NULL))
return 2;
- if (!parse_variables (NULL, &v_variables, &n_variables,
+ if (!parse_variables (default_dict, &v_variables, &n_variables,
PV_APPEND | PV_NO_SCRATCH))
return 0;
{
struct variable *v = v_variables[i];
- if (v->foo != 0)
+ if (v->p.frq.used != 0)
{
msg (SE, _("Variable %s specified multiple times on VARIABLES "
"subcommand."), v->name);
return 0;
}
- v->foo = 1; /* Used simply as a marker. */
+ v->p.frq.used = 1; /* Used simply as a marker. */
v->p.frq.tab.valid = v->p.frq.tab.missing = NULL;
frq_custom_grouped (struct cmd_frequencies *cmd unused)
{
lex_match ('=');
- if ((token == T_ID && is_varname (tokid)) || token == T_ID)
+ if ((token == T_ID && dict_lookup_var (default_dict, tokid) != NULL)
+ || token == T_ID)
for (;;)
{
int i;
int n;
struct variable **v;
- if (!parse_variables (NULL, &v, &n, PV_NO_DUPLICATE | PV_NUMERIC))
+ if (!parse_variables (default_dict, &v, &n,
+ PV_NO_DUPLICATE | PV_NUMERIC))
return 0;
if (lex_match ('('))
{
for (i = 0; i < n; i++)
{
- if (v[i]->foo == 0)
+ if (v[i]->p.frq.used == 0)
msg (SE, _("Variables %s specified on GROUPED but not on "
"VARIABLES."), v[i]->name);
if (v[i]->p.frq.groups != NULL)
free (v);
if (!lex_match ('/'))
break;
- if ((token != T_ID || !is_varname (tokid)) && token != T_ALL)
+ if ((token != T_ID || dict_lookup_var (default_dict, tokid) != NULL)
+ && token != T_ALL)
{
lex_put_back ('/');
break;
struct trns_header h;
struct file_handle *f; /* Associated system file. */
int nvar; /* Number of variables. */
- int *var; /* Indices of variables. */
+ struct variable **var; /* Variables. */
flt64 *case_buf; /* Case transfer buffer. */
};
struct dictionary *dict;
int options = GTSV_OPT_NONE;
- int i;
- int nval;
-
lex_match_id ("GET");
discard_variables ();
dump_dict_variables (dict);
#endif
- /* Set the fv and lv elements of all variables remaining in the
- dictionary. */
- nval = 0;
- for (i = 0; i < dict->nvar; i++)
- {
- struct variable *v = dict->var[i];
-
- v->fv = nval;
- nval += v->nv;
- }
- dict->nval = nval;
- assert (nval);
+ dict_compact_values (dict);
#if DEBUGGING
printf (_("GET translation table from file to memory:\n"));
}
#endif
- restore_dictionary (dict);
+ dict_destroy (default_dict);
+ default_dict = dict;
vfm_source = &get_source;
get_file = handle;
return CMD_SUCCESS;
}
-/* Parses the SAVE (for X==0) and XSAVE (for X==1) commands. */
-/* FIXME: save_dictionary() is too expensive. It would make more
- sense to copy just the first few fields of each variables (up to
- `foo'): that's a SMOP. */
-int
-cmd_save_internal (int x)
+/* Parses the SAVE (for XSAVE==0) and XSAVE (for XSAVE==1)
+ commands. */
+static int
+cmd_save_internal (int xsave)
{
struct file_handle *handle;
struct dictionary *dict;
if (handle == NULL)
return CMD_FAILURE;
- dict = save_dictionary ();
+ dict = dict_clone (default_dict);
#if DEBUGGING
dump_dict_variables (dict);
#endif
- for (i = 0; i < dict->nvar; i++)
- dict->var[i]->foo = i;
+ for (i = 0; i < dict_get_var_cnt (dict); i++)
+ dict_get_var (dict, i)->aux = dict_get_var (default_dict, i);
if (0 == trim_dictionary (dict, &options))
{
fh_close_handle (handle);
inf.compress = !!(options & GTSV_OPT_COMPRESSED);
if (!sfm_write_dictionary (&inf))
{
- free_dictionary (dict);
+ dict_destroy (dict);
fh_close_handle (handle);
return CMD_FAILURE;
}
t->h.proc = save_trns_proc;
t->h.free = save_trns_free;
t->f = handle;
- t->nvar = dict->nvar;
- t->var = xmalloc (sizeof *t->var * dict->nvar);
- for (i = 0; i < dict->nvar; i++)
- t->var[i] = dict->var[i]->foo;
+ t->nvar = dict_get_var_cnt (dict);
+ t->var = xmalloc (sizeof *t->var * t->nvar);
+ for (i = 0; i < t->nvar; i++)
+ t->var[i] = dict_get_var (dict, i)->aux;
t->case_buf = xmalloc (sizeof *t->case_buf * inf.case_size);
- free_dictionary (dict);
+ dict_destroy (dict);
- if (x == 0)
+ if (xsave == 0)
/* SAVE. */
{
procedure (NULL, save_write_case_func, NULL);
- save_trns_free ((struct trns_header *) t);
+ save_trns_free (&t->h);
}
else
/* XSAVE. */
- add_transformation ((struct trns_header *) t);
+ add_transformation (&t->h);
return CMD_SUCCESS;
}
static int
save_write_case_func (struct ccase * c)
{
- save_trns_proc ((struct trns_header *) trns, c);
+ save_trns_proc (&trns->h, c);
return 1;
}
for (i = 0; i < trns->nvar; i++)
{
- struct variable *v = default_dict.var[trns->var[i]];
+ struct variable *v = trns->var[i];
if (v->type == NUMERIC)
{
double src = c->data[v->fv].f;
free (t);
}
-/* Deletes NV variables from DICT, starting at index FIRST. The
- variables must have consecutive indices. The variables are cleared
- and freed. */
-static void
-dict_delete_run (struct dictionary *dict, int first, int nv)
-{
- int i;
-
- for (i = first; i < first + nv; i++)
- {
- clear_variable (dict, dict->var[i]);
- free (dict->var[i]);
- }
- for (i = first; i < dict->nvar - nv; i++)
- {
- dict->var[i] = dict->var[i + nv];
- dict->var[i]->index -= nv;
- }
- dict->nvar -= nv;
-}
-
static int rename_variables (struct dictionary * dict);
/* The GET and SAVE commands have a common structure after the
*OPTIONS, for the GTSV_OPT_SAVE bit, and writes it, for the
GTSV_OPT_COMPRESSED bit. */
/* FIXME: IN, FIRST, LAST, MAP. */
+/* FIXME? Should we call dict_compact_values() on dict as a
+ final step? */
static int
trim_dictionary (struct dictionary *dict, int *options)
{
if (*options & GTSV_OPT_SAVE)
{
- int i;
-
/* Delete all the scratch variables. */
- for (i = 0; i < dict->nvar; i++)
- {
- int j;
-
- if (dict->var[i]->name[0] != '#')
- continue;
-
- /* Find a run of variables to be deleted. */
- for (j = i + 1; j < dict->nvar; j++)
- if (dict->var[j]->name[0] != '#')
- break;
-
- /* Actually delete 'em. */
- dict_delete_run (dict, i, j - i);
- }
+ struct variable **v;
+ size_t nv;
+ size_t i;
+
+ v = xmalloc (sizeof *v * dict_get_var_cnt (dict));
+ nv = 0;
+ for (i = 0; i < dict_get_var_cnt (dict); i++)
+ if (dict_get_var (dict, i)->name[0] == '#')
+ v[nv++] = dict_get_var (dict, i);
+ dict_delete_vars (dict, v, nv);
+ free (v);
}
while ((*options & GTSV_OPT_MATCH_FILES) || lex_match ('/'))
{
struct variable **v;
int nv;
- int i;
lex_match ('=');
if (!parse_variables (dict, &v, &nv, PV_NONE))
return 0;
-
- /* Loop through the variables to delete. */
- for (i = 0; i < nv;)
- {
- int j;
-
- /* Find a run of variables to be deleted. */
- for (j = i + 1; j < nv; j++)
- if (v[j]->index != v[j - 1]->index + 1)
- break;
-
- /* Actually delete 'em. */
- dict_delete_run (dict, v[i]->index, j - i);
- i = j;
- }
+ dict_delete_vars (dict, v, nv);
+ free (v);
}
else if (lex_match_id ("KEEP"))
{
struct variable **v;
int nv;
+ int i;
lex_match ('=');
if (!parse_variables (dict, &v, &nv, PV_NONE))
return 0;
- /* Reorder the dictionary so that the kept variables are at
- the beginning. */
- {
- int i1;
-
- for (i1 = 0; i1 < nv; i1++)
- {
- int i2 = v[i1]->index;
-
- /* Swap variables with indices i1 and i2. */
- struct variable *t = dict->var[i1];
- dict->var[i1] = dict->var[i2];
- dict->var[i2] = t;
- dict->var[i1]->index = i1;
- dict->var[i2]->index = i2;
- }
-
- free (v);
- }
-
- /* Delete all but the first NV variables from the
- dictionary. */
- {
- int i;
- for (i = nv; i < dict->nvar; i++)
- {
- clear_variable (dict, dict->var[i]);
- free (dict->var[i]);
- }
- }
- dict->var = xrealloc (dict->var, sizeof *dict->var * nv);
- dict->nvar = nv;
+ /* Move the specified variables to the beginning. */
+ dict_reorder_vars (dict, v, nv);
+
+ /* Delete the remaining variables. */
+ v = xrealloc (v, (dict_get_var_cnt (dict) - nv) * sizeof *v);
+ for (i = nv; i < dict_get_var_cnt (dict); i++)
+ v[i - nv] = dict_get_var (dict, i);
+ dict_delete_vars (dict, v, dict_get_var_cnt (dict) - nv);
+ free (v);
}
else if (lex_match_id ("RENAME"))
{
return 0;
}
- if (dict->nvar == 0)
+ if (dict_get_var_cnt (dict) == 0)
{
msg (SE, _("All variables deleted from system file dictionary."));
return 0;
struct variable **v;
char **new_names;
int nv, nn;
+ char *err_name;
int group;
return 0;
if (!strncmp (tokid, v->name, 8))
return 1;
- if (is_dict_varname (dict, tokid))
+ if (dict_lookup_var (dict, tokid) != NULL)
{
msg (SE, _("Cannot rename %s as %s because there already exists "
"a variable named %s. To rename variables with "
return 0;
}
- rename_variable (dict, v, tokid);
+ dict_rename_var (dict, v, tokid);
lex_get ();
return 1;
}
int old_nv = nv;
if (!parse_variables (dict, &v, &nv, PV_NO_DUPLICATE | PV_APPEND))
- goto lossage;
+ goto done;
if (!lex_match ('='))
{
msg (SE, _("`=' expected after variable list."));
- goto lossage;
+ goto done;
}
if (!parse_DATA_LIST_vars (&new_names, &nn, PV_APPEND | PV_NO_SCRATCH))
- goto lossage;
+ goto done;
if (nn != nv)
{
- msg (SE, _("Number of variables on left side of `=' (%d) do not "
+ msg (SE, _("Number of variables on left side of `=' (%d) does not "
"match number of variables on right side (%d), in "
"parenthesized group %d of RENAME subcommand."),
nv - old_nv, nn - old_nv, group);
- goto lossage;
+ goto done;
}
if (!lex_force_match (')'))
- goto lossage;
+ goto done;
group++;
}
- for (i = 0; i < nv; i++)
- hsh_force_delete (dict->name_tab, v[i]);
- for (i = 0; i < nv; i++)
+ if (!dict_rename_vars (dict, v, new_names, nv, &err_name))
{
- strcpy (v[i]->name, new_names[i]);
- if (NULL != hsh_insert (dict->name_tab, v[i]))
- {
- msg (SE, _("Duplicate variables name %s."), v[i]->name);
- goto lossage;
- }
+ msg (SE, _("Requested renaming duplicates variable name %s."), err_name);
+ goto done;
}
success = 1;
-lossage:
- /* The label is a bit of a misnomer, we actually come here on any
- sort of return. */
+done:
for (i = 0; i < nn; i++)
free (new_names[i]);
free (new_names);
static void
get_source_read (void)
{
- while (sfm_read_case (get_file, temp_case->data, &default_dict)
+ while (sfm_read_case (get_file, temp_case->data, default_dict)
&& write_case ())
;
get_source_destroy_source ();
union value *input; /* Input record. */
};
-/* All the files mentioned on FILE= or TABLE=. */
+/* All the files mentioned on FILE or TABLE. */
static struct mtf_file *mtf_head, *mtf_tail;
/* Variables on the BY subcommand. */
/* Master dictionary. */
static struct dictionary *mtf_master;
+/* Used to determine whether we've already initialized this
+ variable. */
+static unsigned mtf_seq_num;
+
+/* Sequence numbers for each variable in mtf_master. */
+static unsigned *mtf_seq_nums;
+
static void mtf_free (void);
static void mtf_free_file (struct mtf_file *file);
static int mtf_merge_dictionary (struct mtf_file *f);
mtf_head = mtf_tail = NULL;
mtf_by = NULL;
mtf_n_by = 0;
- mtf_master = new_dictionary (0);
- mtf_master->N = default_dict.N;
+ mtf_master = dict_create ();
+ mtf_seq_num = 0;
+ mtf_seq_nums = NULL;
+ dict_set_case_limit (mtf_master, dict_get_case_limit (default_dict));
do
{
goto lossage;
}
else
- file->dict = &default_dict;
+ file->dict = default_dict;
if (!mtf_merge_dictionary (file))
goto lossage;
}
strcpy (name, tokid);
lex_get ();
- if (!create_variable (mtf_master, name, NUMERIC, 0))
+ if (!dict_create_var (mtf_master, name, 0))
{
msg (SE, _("Duplicate variable name %s while creating %s "
"variable."),
for (i = 0; i < mtf_n_by; i++)
{
- iter->by[i] = find_dict_variable (iter->dict, mtf_by[i]->name);
+ iter->by[i] = dict_lookup_var (iter->dict, mtf_by[i]->name);
if (iter->by[i] == NULL)
{
msg (SE, _("File %s lacks BY variable %s."),
because there's no function to read a record from the active
file; instead, it has to be done using callbacks.
- FIXME: A better algorithm would use a heap for finding minimum
- values, or replacement selection, as described by Knuth in _Art
- of Computer Programming, Vol. 3_. The SORT CASES procedure does
- this, and perhaps some of its code could be adapted. */
+ FIXME: For merging large numbers of files (more than 10?) a
+ better algorithm would use a heap for finding minimum
+ values, or replacement selection, as described by Knuth in
+ _Art of Computer Programming, Vol. 3_. The SORT CASES
+ procedure does this, and perhaps some of its code could be
+ adapted. */
if (!(seen & 2))
discard_variables ();
temp_dict = mtf_master;
temp_trns = n_trns;
+ mtf_seq_nums = xmalloc (dict_get_var_cnt (mtf_master)
+ * sizeof *mtf_seq_nums);
+ memset (mtf_seq_nums, 0,
+ dict_get_var_cnt (mtf_master) * sizeof *mtf_seq_nums);
+
process_active_file (mtf_read_nonactive_records, mtf_processing,
mtf_processing_finish);
mtf_master = NULL;
mtf_free_file (struct mtf_file *file)
{
fh_close_handle (file->handle);
- if (file->dict && file->dict != &default_dict)
- free_dictionary (file->dict);
+ if (file->dict != NULL && file->dict != default_dict)
+ dict_destroy (file->dict);
free (file->by);
if (file->handle)
free (file->input);
free (mtf_by);
if (mtf_master)
- free_dictionary (mtf_master);
+ dict_destroy (mtf_master);
+ free (mtf_seq_nums);
}
/* Remove *FILE from the mtf_file chain. Make *FILE point to the next
{
int i;
- for (i = 0; i < f->dict->nvar; i++)
+ for (i = 0; i < dict_get_var_cnt (f->dict); i++)
{
- struct variable *v = f->dict->var[i];
+ struct variable *v = dict_get_var (f->dict, i);
if (v->type == NUMERIC)
compaction_case->data[v->p.mtf.master->fv].f = SYSMIS;
if (iter->handle)
{
assert (iter->input == NULL);
- iter->input = xmalloc (sizeof *iter->input * iter->dict->nval);
+ iter->input = xmalloc (sizeof *iter->input
+ * dict_get_value_cnt (iter->dict));
if (!sfm_read_case (iter->handle, iter->input, iter->dict))
mtf_delete_file_in_place (&iter);
return 0;
}
-/* Used to determine whether we've already initialized this
- variable. */
-static int mtf_seq_no = 0;
-
/* Perform one iteration of steps 3...7 above. */
static int
mtf_processing (struct ccase *c unused)
}
/* Next sequence number. */
- mtf_seq_no++;
+ mtf_seq_num++;
/* Store data to all the records we are using. */
if (min_tail)
{
int i;
- for (i = 0; i < iter->dict->nvar; i++)
+ for (i = 0; i < dict_get_var_cnt (iter->dict); i++)
{
- struct variable *v = iter->dict->var[i];
+ struct variable *v = dict_get_var (iter->dict, i);
- if (v->p.mtf.master->foo == mtf_seq_no)
+ if (mtf_seq_nums[v->p.mtf.master->index] == mtf_seq_num)
continue;
- v->p.mtf.master->foo = mtf_seq_no;
+ mtf_seq_nums[v->p.mtf.master->index] = mtf_seq_num;
#if 0
printf ("%s/%s: dest-fv=%d, src-fv=%d\n",
{
int i;
- for (i = 0; i < iter->dict->nvar; i++)
+ for (i = 0; i < dict_get_var_cnt (iter->dict); i++)
{
- struct variable *v = iter->dict->var[i];
+ struct variable *v = dict_get_var (iter->dict, i);
- if (v->p.mtf.master->foo == mtf_seq_no)
+ if (mtf_seq_nums[v->p.mtf.master->index] == mtf_seq_num)
continue;
- v->p.mtf.master->foo = mtf_seq_no;
+ mtf_seq_nums[v->p.mtf.master->index] = mtf_seq_num;
#if 0
printf ("%s/%s: dest-fv=%d\n",
{
struct dictionary *const m = mtf_master;
struct dictionary *d = f->dict;
-
- if (d->label && m->label == NULL)
- m->label = xstrdup (d->label);
+ const char *d_docs, *m_docs;
+
+ if (dict_get_label (m) == NULL)
+ dict_set_label (m, dict_get_label (d));
- if (d->documents)
+ d_docs = dict_get_documents (d);
+ m_docs = dict_get_documents (m);
+ if (d_docs != NULL)
{
- m->documents = xrealloc (m->documents,
- 80 * (m->n_documents + d->n_documents));
- memcpy (&m->documents[80 * m->n_documents],
- d->documents, 80 * d->n_documents);
- m->n_documents += d->n_documents;
+ if (m_docs == NULL)
+ dict_set_documents (m, d_docs);
+ else
+ {
+ char *new_docs;
+ size_t new_len;
+
+ new_len = strlen (m_docs) + strlen (d_docs);
+ new_docs = xmalloc (new_len + 1);
+ strcpy (new_docs, m_docs);
+ strcat (new_docs, d_docs);
+ dict_set_documents (m, new_docs);
+ free (new_docs);
+ }
}
-
+
+ dict_compact_values (d);
+
{
int i;
- d->nval = 0;
- for (i = 0; i < d->nvar; i++)
+ for (i = 0; i < dict_get_var_cnt (d); i++)
{
- struct variable *dv = d->var[i];
- struct variable *mv = find_dict_variable (m, dv->name);
+ struct variable *dv = dict_get_var (d, i);
+ struct variable *mv = dict_lookup_var (m, dv->name);
- dv->fv = d->nval;
- d->nval += dv->nv;
-
assert (dv->type == ALPHA || dv->width == 0);
assert (!mv || mv->type == ALPHA || mv->width == 0);
if (mv && dv->width == mv->width)
if (val_labs_count (dv->val_labs)
&& !val_labs_count (mv->val_labs))
mv->val_labs = val_labs_copy (dv->val_labs);
- if (dv->miss_type != MISSING_NONE && mv->miss_type == MISSING_NONE)
+ if (dv->miss_type != MISSING_NONE
+ && mv->miss_type == MISSING_NONE)
copy_missing_values (mv, dv);
}
if (mv && dv->label && !mv->label)
mv->label = xstrdup (dv->label);
- if (!mv)
- {
- mv = force_dup_variable (m, dv, dv->name);
-
- /* Used to make sure we initialize each variable in the
- master dictionary exactly once per case. */
- mv->foo = mtf_seq_no;
- }
+ if (!mv)
+ {
+ mv = dict_clone_var (m, dv, dv->name);
+ assert (mv != NULL);
+ }
else if (mv->width != dv->width)
{
msg (SE, _("Variable %s in file %s (%s) has different "
int options = GTSV_OPT_NONE;
int type;
- int i;
- int nval;
-
lex_match_id ("IMPORT");
for (;;)
dump_dict_variables (dict);
#endif
- /* Set the fv and lv elements of all variables remaining in the
- dictionary. */
- nval = 0;
- for (i = 0; i < dict->nvar; i++)
- {
- struct variable *v = dict->var[i];
-
- v->fv = nval;
- nval += v->nv;
- }
- dict->nval = nval;
- assert (nval);
+ dict_compact_values (dict);
#if DEBUGGING
printf (_("IMPORT translation table from file to memory:\n"));
}
#endif
- restore_dictionary (dict);
+ dict_destroy (default_dict);
+ default_dict = dict;
vfm_source = &import_source;
get_file = handle;
static void
import_source_read (void)
{
- while (pfm_read_case (get_file, temp_case->data, &default_dict)
+ while (pfm_read_case (get_file, temp_case->data, default_dict)
&& write_case ())
;
get_source_destroy_source ();
if (handle == NULL)
return CMD_FAILURE;
- dict = save_dictionary ();
+ dict = dict_clone (default_dict);
#if DEBUGGING
dump_dict_variables (dict);
#endif
- for (i = 0; i < dict->nvar; i++)
- dict->var[i]->foo = i;
+ for (i = 0; i < dict_get_var_cnt (dict); i++)
+ dict_get_var (dict, i)->aux = dict_get_var (default_dict, i);
if (0 == trim_dictionary (dict, &options))
{
fh_close_handle (handle);
/* Write dictionary. */
if (!pfm_write_dictionary (handle, dict))
{
- free_dictionary (dict);
+ dict_destroy (dict);
fh_close_handle (handle);
return CMD_FAILURE;
}
t->h.proc = save_trns_proc;
t->h.free = save_trns_free;
t->f = handle;
- t->nvar = dict->nvar;
- t->var = xmalloc (sizeof *t->var * dict->nvar);
- for (i = 0; i < dict->nvar; i++)
- t->var[i] = dict->var[i]->foo;
- t->case_buf = xmalloc (sizeof *t->case_buf * dict->nvar);
- free_dictionary (dict);
+ t->nvar = dict_get_var_cnt (dict);
+ t->var = xmalloc (sizeof *t->var * t->nvar);
+ for (i = 0; i < t->nvar; i++)
+ t->var[i] = dict_get_var (dict, i)->aux;
+ t->case_buf = xmalloc (sizeof *t->case_buf * t->nvar);
+ dict_destroy (dict);
procedure (NULL, export_write_case_func, NULL);
- save_trns_free ((struct trns_header *) t);
+ save_trns_free (&t->h);
return CMD_SUCCESS;
}
for (i = 0; i < trns->nvar; i++)
{
- struct variable *v = default_dict.var[trns->var[i]];
+ struct variable *v = trns->var[i];
if (v->type == NUMERIC)
*p++ = c->data[v->fv];
(*p++).c = c->data[v->fv].s;
}
- printf (".");
- fflush (stdout);
-
pfm_write_case (trns->f, (union value *) trns->case_buf);
return 1;
}
02111-1307, USA. */
#include <config.h>
+#include "getline.h"
#include <assert.h>
#include <stdio.h>
#include <errno.h>
#include "alloc.h"
#include "error.h"
#include "filename.h"
-#include "getline.h"
#include "lexer.h"
+#include "repeat.h"
#include "settings.h"
#include "str.h"
#include "tab.h"
}
/* Display a welcoming message. */
-void
+static void
welcome (void)
{
getl_welcomed = 1;
02111-1307, USA. */
#include <config.h>
-
+#include "glob.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include "do-ifP.h"
#include "error.h"
#include "expr.h"
+#include "file-handle.h"
#include "filename.h"
#include "getline.h"
#include "hash.h"
#include "vfm.h"
/* var.h */
-struct dictionary default_dict;
+struct dictionary *default_dict;
struct expression *process_if_expr;
struct ccase *temp_case;
#endif
/* var.h */
- default_dict.name_tab = hsh_create (8, compare_variables, hash_variable,
- NULL, NULL);
+ default_dict = dict_create ();
vec_init (&reinit_sysmis);
vec_init (&reinit_blanks);
logfile = NULL;
/* file-handle.h */
- {
- extern void fh_init_files (void);
-
- fh_init_files ();
- }
+ fh_init_files ();
get_date ();
}
--- /dev/null
+/* PSPP - computes sample statistics.
+ Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Written by Ben Pfaff <blp@gnu.org>.
+
+ 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 the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#if !INCLUDED_GLOB_H
+#define INCLUDED_GLOB_H 1
+
+void init_glob (int argc unused, char **argv);
+
+#endif /* glob.h */
02111-1307, USA. */
#include <config.h>
+#include "font.h"
#include <assert.h>
#include <stdio.h>
#include <errno.h>
#include "alloc.h"
#include "error.h"
#include "filename.h"
-#include "font.h"
#include "hash.h"
#include "pool.h"
#include "str.h"
02111-1307, USA. */
#include <config.h>
+#include "hash.h"
#include <assert.h>
#include <limits.h>
#include <stdlib.h>
#include "algorithm.h"
#include "alloc.h"
-#include "hash.h"
#include "misc.h"
#include "str.h"
}
}
-/* Colin Plumb's "one-at-a-time" hash, for bytes. */
+/* Fowler-Noll-Vo hash constants, for 32-bit word sizes. */
+#define FNV_32_PRIME 16777619u
+#define FNV_32_BASIS 2166136261u
+
+/* Fowler-Noll-Vo 32-bit hash, for bytes. */
unsigned
hsh_hash_bytes (const void *buf_, size_t size)
{
const unsigned char *buf = buf_;
- unsigned hash = 0;
+ unsigned hash;
assert (buf != NULL);
- while (size-- > 0)
- {
- hash += *buf++;
- hash += (hash << 10);
- hash ^= (hash >> 6);
- }
- hash += (hash << 3);
- hash ^= (hash >> 11);
- hash += (hash << 15);
+
+ hash = FNV_32_BASIS;
+ while (size-- > 0)
+ hash = (hash * FNV_32_PRIME) ^ *buf++;
+
return hash;
}
-/* Colin Plumb's "one-at-a-time" hash, for strings. */
+/* Fowler-Noll-Vo 32-bit hash, for strings. */
unsigned
hsh_hash_string (const char *s_)
{
const unsigned char *s = s_;
- unsigned hash = 0;
+ unsigned hash;
assert (s != NULL);
- while (*s != '\0')
- {
- hash += *s++;
- hash += (hash << 10);
- hash ^= (hash >> 6);
- }
- hash += (hash << 3);
- hash ^= (hash >> 11);
- hash += (hash << 15);
+
+ hash = FNV_32_BASIS;
+ while (*s != '\0')
+ hash = (hash * FNV_32_PRIME) ^ *s++;
+
return hash;
}
/* Dereferences void ** pointers and passes them to the hash
comparison function. */
-int
+static int
comparison_helper (const void *a_, const void *b_, void *h_)
{
void *const *a = a_;
02111-1307, USA. */
#include <config.h>
+#include "heap.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
-#include "heap.h"
#if STANDALONE
#define GLOBAL_DEBUGGING 1
/* This module implements a priority queue as a heap as described in
Knuth 5.2.3. This is a first-in-smallest-out priority queue. */
+#include <stddef.h>
+
/* One element of a heap. */
struct heap_elem
{
#if !NO_HTML
#include <config.h>
+#include "htmlP.h"
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include "error.h"
#include "filename.h"
#include "getline.h"
-#include "htmlP.h"
#include "output.h"
#include "som.h"
#include "tab.h"
static int postopen (struct file_ext *);
static int preclose (struct file_ext *);
-int
+static int
html_open_global (struct outp_class *this unused)
{
return 1;
}
-int
+static int
html_close_global (struct outp_class *this unused)
{
return 1;
}
-int
+static int
html_preopen_driver (struct outp_driver *this)
{
struct html_driver_ext *x;
return 1;
}
-int
+static int
html_postopen_driver (struct outp_driver *this)
{
struct html_driver_ext *x = this->ext;
return 1;
}
-int
+static int
html_close_driver (struct outp_driver *this)
{
struct html_driver_ext *x = this->ext;
};
static struct outp_option_info option_info;
-void
+static void
html_option (struct outp_driver *this, const char *key, const struct string *val)
{
struct html_driver_ext *x = this->ext;
return 1;
}
-int
+static int
html_open_page (struct outp_driver *this)
{
struct html_driver_ext *x = this->ext;
return !ferror (x->file.file);
}
-int
+static int
html_close_page (struct outp_driver *this)
{
struct html_driver_ext *x = this->ext;
static void output_tab_table (struct outp_driver *, struct tab_table *);
-void
+static void
html_submit (struct outp_driver *this, struct som_table *s)
{
extern struct som_table_class tab_table_class;
#include "error.h"
#include "expr.h"
#include "file-handle.h"
-#include "inpt-pgm.h"
#include "lexer.h"
#include "misc.h"
#include "str.h"
#include "debug-print.h"
-/* A bit-vector of two-bit entries. The array tells INPUT PROGRAM how
- to initialize each `value'. Modified by envector(), devector(),
- which are called by create_variable(), also by LEAVE, COMPUTE(!). */
-unsigned char *inp_init;
+/* Indicates how a `union value' should be initialized. */
+enum value_init_type
+ {
+ INP_NUMERIC = 01, /* Numeric. */
+ INP_STRING = 0, /* String. */
+
+ INP_INIT_ONCE = 02, /* Initialize only once. */
+ INP_REINIT = 0, /* Reinitialize for each iteration. */
+ };
-/* Number of bytes allocated for inp_init. */
-size_t inp_init_size;
+/* Array that tells INPUT PROGRAM how to initialize each `union
+ value'. */
+static enum value_init_type *inp_init;
-/* Number of `values' created inside INPUT PROGRAM. */
-static int inp_nval;
+/* Number of bytes allocated for inp_init. */
+static size_t inp_nval;
static int end_case_trns_proc (struct trns_header *, struct ccase *);
static int end_file_trns_proc (struct trns_header * t, struct ccase * c);
vfm_source = &input_program_source;
- inp_init = NULL;
- inp_init_size = 0;
-
return lex_end_of_command ();
}
int
cmd_end_input_program (void)
{
+ size_t i;
+
lex_match_id ("END");
lex_match_id ("INPUT");
lex_match_id ("PROGRAM");
return CMD_FAILURE;
}
- if (default_dict.nval == 0)
+ if (dict_get_value_cnt (default_dict) == 0)
msg (SW, _("No data-input or transformation commands specified "
"between INPUT PROGRAM and END INPUT PROGRAM."));
transformations. */
f_trns = n_trns;
- /* Mark the boundary between input program `values' and
- later-created `values'. */
- inp_nval = default_dict.nval;
+ /* Figure out how to initialize temp_case. */
+ inp_nval = dict_get_value_cnt (default_dict);
+ inp_init = xmalloc (inp_nval * sizeof *inp_init);
+ for (i = 0; i < inp_nval; i++)
+ inp_init[i] = -1;
+ for (i = 0; i < dict_get_var_cnt (default_dict); i++)
+ {
+ struct variable *var = dict_get_var (default_dict, i);
+ enum value_init_type value_init;
+ size_t j;
+
+ value_init = var->type == NUMERIC ? INP_NUMERIC : INP_STRING;
+ value_init |= var->left ? INP_INIT_ONCE : INP_REINIT;
+
+ for (j = 0; j < var->nv; j++)
+ inp_init[j + var->fv] = value_init;
+ }
+ for (i = 0; i < inp_nval; i++)
+ assert (inp_init[i] != -1);
return lex_end_of_command ();
}
static void
init_case (void)
{
- union value *val = temp_case->data;
- unsigned char *cp = inp_init;
- unsigned char c;
- int i, j;
-
- /* This code is 2-3X the complexity it might be, but I felt like
- it. It initializes temp_case union values to 0, or SYSMIS, or
- blanks, as appropriate. */
- for (i = 0; i < inp_nval / 4; i++)
- {
- c = *cp++;
- for (j = 0; j < 4; j++)
- {
- switch (c & INP_MASK)
- {
- case INP_NUMERIC | INP_RIGHT:
- val++->f = SYSMIS;
- break;
- case INP_NUMERIC | INP_LEFT:
- val++->f = 0.0;
- break;
- case INP_STRING | INP_RIGHT:
- case INP_STRING | INP_LEFT:
- memset (val++->s, ' ', MAX_SHORT_STRING);
- break;
- }
- c >>= 2;
- }
- }
- if (inp_nval % 4)
- {
- c = *cp;
- for (j = 0; j < inp_nval % 4; j++)
- {
- switch (c & INP_MASK)
- {
- case INP_NUMERIC | INP_RIGHT:
- val++->f = SYSMIS;
- break;
- case INP_NUMERIC | INP_LEFT:
- val++->f = 0.0;
- break;
- case INP_STRING | INP_RIGHT:
- case INP_STRING | INP_LEFT:
- memset (val++->s, ' ', MAX_SHORT_STRING);
- break;
- }
- c >>= 2;
- }
- }
+ size_t i;
+
+ for (i = 0; i < inp_nval; i++)
+ switch (inp_init[i])
+ {
+ case INP_NUMERIC | INP_INIT_ONCE:
+ temp_case->data[i].f = 0.0;
+ break;
+ case INP_NUMERIC | INP_REINIT:
+ temp_case->data[i].f = SYSMIS;
+ break;
+ case INP_STRING | INP_INIT_ONCE:
+ case INP_STRING | INP_REINIT:
+ memset (temp_case->data[i].s, ' ', sizeof temp_case->data[i].s);
+ break;
+ default:
+ assert (0);
+ }
}
/* Clears temp_case. Called between reading successive records. */
static void
clear_case (void)
{
- union value *val = temp_case->data;
- unsigned char *cp = inp_init;
- unsigned char c;
- int i, j;
-
- /* This code is 2-3X the complexity it might be, but I felt like
- it. It initializes temp_case values to SYSMIS, or
- blanks, or does nothing, as appropriate. */
- for (i = 0; i < inp_nval / 4; i++)
- {
- c = *cp++;
- for (j = 0; j < 4; j++)
- {
- if (!(c & INP_LEFT))
- {
- if (c & INP_STRING)
- memset (val->s, ' ', MAX_SHORT_STRING);
- else
- val->f = SYSMIS;
- }
- val++;
- c >>= 2;
- }
- }
-
- if (inp_nval % 4)
- {
- c = *cp;
- for (j = 0; j < inp_nval % 4; j++)
- {
- if (!(c & INP_LEFT))
- {
- if (c & INP_STRING)
- memset (val->s, ' ', MAX_SHORT_STRING);
- else
- val->f = SYSMIS;
- }
- val++;
- c >>= 2;
- }
- }
+ size_t i;
+
+ for (i = 0; i < inp_nval; i++)
+ switch (inp_init[i])
+ {
+ case INP_NUMERIC | INP_INIT_ONCE:
+ break;
+ case INP_NUMERIC | INP_REINIT:
+ temp_case->data[i].f = SYSMIS;
+ break;
+ case INP_STRING | INP_INIT_ONCE:
+ break;
+ case INP_STRING | INP_REINIT:
+ memset (temp_case->data[i].s, ' ', sizeof temp_case->data[i].s);
+ break;
+ default:
+ assert (0);
+ }
}
/* Executes each transformation in turn on a `blank' case. When a
transformation fails, returning -2, then that's the end of the
file. -1 means go on to the next transformation. Otherwise the
return value is the index of the transformation to go to next. */
-void
+static void
input_program_source_read (void)
{
int i;
+++ /dev/null
-/* PSPP - computes sample statistics.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
- Written by Ben Pfaff <blp@gnu.org>.
-
- 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 the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
-
-#if !inpt_pgm_h
-#define inpt_pgm_h 1
-
-/* Bitmasks to indicate variable type. */
-enum
- {
- INP_MASK = 03, /* 2#11. */
-
- INP_NUMERIC = 0, /* Numeric. */
- INP_STRING = 01, /* String. */
-
- INP_RIGHT = 0, /* Ordinary. */
- INP_LEFT = 02 /* Scratch or LEAVE. */
- };
-
-extern unsigned char *inp_init;
-extern size_t inp_init_size;
-
-#endif /* !inpt_pgm_h */
02111-1307, USA. */
#include <config.h>
+#include "lexer.h"
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include "command.h"
#include "error.h"
#include "getline.h"
-#include "lexer.h"
#include "magic.h"
#include "settings.h"
#include "str.h"
if (cmd.last == NOT_LONG)
cmd.last = LONG_MAX;
if (!cmd.sbc_variables)
- fill_all_vars (&cmd.v_variables, &cmd.n_variables,
- FV_NO_SYSTEM | FV_NO_SCRATCH);
+ dict_get_vars (default_dict, &cmd.v_variables, &cmd.n_variables,
+ (1u << DC_SYSTEM) | (1u << DC_SCRATCH));
if (cmd.n_variables == 0)
{
msg (SE, _("No variables specified."));
/* Weighting variable. */
if (cmd.weight == LST_WEIGHT)
{
- update_weighting (&default_dict);
- if (default_dict.weight_index != -1)
+ if (dict_get_weight (default_dict) != NULL)
{
int i;
for (i = 0; i < cmd.n_variables; i++)
- if (cmd.v_variables[i]->index == default_dict.weight_index)
+ if (cmd.v_variables[i] == dict_get_weight (default_dict))
break;
if (i >= cmd.n_variables)
{
(cmd.n_variables
* sizeof *cmd.v_variables));
cmd.v_variables[cmd.n_variables - 1]
- = default_dict.var[default_dict.weight_index];
+ = dict_get_weight (default_dict);
}
}
else
/* Parse indexing clause. */
if (token == T_ID && lex_look_ahead () == '=')
{
- struct variable *v = find_variable (tokid);
+ struct variable *v = dict_lookup_var (default_dict, tokid);
two->flags |= LPC_INDEX;
/* Find variable; create if necessary. */
if (name[0])
{
- two->index = find_variable (name);
+ two->index = dict_lookup_var (default_dict, name);
if (!two->index)
{
- two->index = force_create_variable (&default_dict, name, NUMERIC, 0);
+ two->index = dict_create_var (default_dict, name, 0);
#if DEBUGGING
envector (two->index);
#endif
02111-1307, USA. */
#include <config.h>
+#include "main.h"
#include <assert.h>
#include <stdio.h>
+#include "cmdline.h"
#include "command.h"
#include "error.h"
#include "getline.h"
+#include "glob.h"
#include "lexer.h"
#include "output.h"
int
main (int argc, char **argv)
{
- void init_glob (int, char **); /* Exported by glob.c. */
- void parse_command_line (int, char **); /* Exported by cmdline.c */
-
/* Initialization. */
if (!outp_init ())
err_hcf (0);
if (strcmp (v[i], "ROWTYPE_"))
{
- new_var = force_create_variable (&default_dict, v[i],
- NUMERIC, 0);
+ new_var = dict_create_var (default_dict, v[i], 0);
+ assert (new_var != NULL);
new_var->p.mxd.vartype = MXD_CONTINUOUS;
new_var->p.mxd.subtype = i;
}
}
{
- rowtype_ = force_create_variable (&default_dict, "ROWTYPE_",
- ALPHA, 8);
+ rowtype_ = dict_create_var (default_dict, "ROWTYPE_", 8);
+ assert (rowtype_ != NULL);
rowtype_->p.mxd.vartype = MXD_ROWTYPE;
rowtype_->p.mxd.subtype = 0;
}
goto lossage;
}
- if (!is_varname (tokid)
+ if (dict_lookup_var (default_dict, tokid) == NULL
&& (lex_look_ahead () == '.' || lex_look_ahead () == '/'))
{
if (!strcmp (tokid, "ROWTYPE_") || !strcmp (tokid, "VARNAME_"))
goto lossage;
}
- single_split = force_create_variable (&default_dict, tokid,
- NUMERIC, 0);
+ single_split = dict_create_var (default_dict, tokid, 0);
+ assert (single_split != NULL);
lex_get ();
single_split->p.mxd.vartype = MXD_CONTINUOUS;
- default_dict.n_splits = 1;
- default_dict.splits = xmalloc (2 * sizeof *default_dict.splits);
- default_dict.splits[0] = single_split;
- default_dict.splits[1] = NULL;
+ dict_set_split_vars (default_dict, &single_split, 1);
}
else
{
- struct variable **v;
+ struct variable **split;
int n;
- if (!parse_variables (NULL, &v, &n, PV_NO_DUPLICATE))
+ if (!parse_variables (default_dict, &split, &n, PV_NO_DUPLICATE))
goto lossage;
- default_dict.n_splits = n;
- default_dict.splits = v = xrealloc (v, sizeof *v * (n + 1));
- v[n] = NULL;
+ dict_set_split_vars (default_dict, split, n);
}
{
- int i;
-
- for (i = 0; i < default_dict.n_splits; i++)
- {
- if (default_dict.splits[i]->p.mxd.vartype != MXD_CONTINUOUS)
+ struct variable *const *split = dict_get_split_vars (default_dict);
+ size_t split_cnt = dict_get_split_cnt (default_dict);
+ int i;
+
+ for (i = 0; i < split_cnt; i++)
+ {
+ if (split[i]->p.mxd.vartype != MXD_CONTINUOUS)
{
msg (SE, _("Split variable %s is already another type."),
tokid);
goto lossage;
}
- default_dict.splits[i]->p.mxd.vartype = MXD_SPLIT;
- default_dict.splits[i]->p.mxd.subtype = i;
- }
+ split[i]->p.mxd.vartype = MXD_SPLIT;
+ split[i]->p.mxd.subtype = i;
+ }
}
}
else if (lex_match_id ("FACTORS"))
}
seen |= 4;
- if (!parse_variables (NULL, &factors, &n_factors, PV_NONE))
+ if (!parse_variables (default_dict, &factors, &n_factors, PV_NONE))
goto lossage;
{
/* Create VARNAME_. */
{
- varname_ = force_create_variable (&default_dict, "VARNAME_",
- ALPHA, 8);
+ varname_ = dict_create_var (default_dict, "VARNAME_", 8);
+ assert (varname_ != NULL);
varname_->p.mxd.vartype = MXD_VARNAME;
varname_->p.mxd.subtype = 0;
}
/* Sort the dictionary variables into the desired order for the
system file output. */
{
- int i;
-
- qsort (default_dict.var, default_dict.nvar, sizeof *default_dict.var,
- compare_variables_by_mxd_vartype);
+ struct variable **v;
+ size_t nv;
- for (i = 0; i < default_dict.nvar; i++)
- default_dict.var[i]->index = i;
+ dict_get_vars (default_dict, &v, &nv, 0);
+ qsort (v, nv, sizeof *v, compare_variables_by_mxd_vartype);
+ dict_reorder_vars (default_dict, v, nv);
+ free (v);
}
/* Set formats. */
int i;
first_continuous = -1;
- for (i = 0; i < default_dict.nvar; i++)
+ for (i = 0; i < dict_get_var_cnt (default_dict); i++)
{
- struct variable *v = default_dict.var[i];
+ struct variable *v = dict_get_var (default_dict, i);
int type = v->p.mxd.vartype;
assert (type >= 0 && type < MXD_COUNT);
else
assert (0);
- if (default_dict.n_splits)
+ if (dict_get_split_cnt (default_dict) != 0)
{
int i;
printf ("\t/SPLIT=");
- for (i = 0; i < default_dict.n_splits; i++)
- printf ("%s ", default_dict.splits[i]->name);
+ for (i = 0; i < dict_get_split_cnt (default_dict); i++)
+ printf ("%s ", dict_get_split_vars (default_dict)[i]->name);
if (single_split)
printf ("\t/* single split");
printf ("\n");
cells = 1;
mtoken = MNULL;
- split_values = xmalloc (sizeof *split_values * default_dict.n_splits);
+ split_values = xmalloc (sizeof *split_values
+ * dict_get_split_cnt (default_dict));
nr_factor_values = xmalloc (sizeof *nr_factor_values * n_factors * cells);
max_cell_index = 0;
if (mtoken != MNUM)
{
msg (SE, _("expecting value for %s %s"),
- default_dict.var[j]->name, context ());
+ dict_get_var (default_dict, j)->name, context ());
return 0;
}
nr_output_data ();
- if (default_dict.n_splits == 0 || !another_token ())
+ if (dict_get_split_cnt (default_dict) == 0 || !another_token ())
return 1;
}
}
nr_read_splits (int compare)
{
static int just_read = 0;
+ size_t split_cnt;
+ size_t i;
if (compare && just_read)
{
return 1;
}
- if (default_dict.n_splits == 0)
+ if (dict_get_split_vars (default_dict) == NULL)
return 1;
if (single_split)
{
if (!compare)
- split_values[0] = ++default_dict.splits[0]->p.mxd.subtype;
+ split_values[0]
+ = ++dict_get_split_vars (default_dict)[0]->p.mxd.subtype;
return 1;
}
if (!compare)
just_read = 1;
-
- {
- int i;
-
- for (i = 0; i < default_dict.n_splits; i++)
- {
- if (!mget_token ())
- return 0;
- if (mtoken != MNUM)
- {
- msg (SE, _("Syntax error expecting SPLIT FILE value %s."),
- context ());
- return 0;
- }
- if (!compare)
- split_values[i] = mtokval;
- else if (split_values[i] != mtokval)
- {
- msg (SE, _("Expecting value %g for %s."),
- split_values[i], default_dict.splits[i]->name);
- return 0;
- }
- }
- }
+ split_cnt = dict_get_split_cnt (default_dict);
+ for (i = 0; i < split_cnt; i++)
+ {
+ if (!mget_token ())
+ return 0;
+ if (mtoken != MNUM)
+ {
+ msg (SE, _("Syntax error expecting SPLIT FILE value %s."),
+ context ());
+ return 0;
+ }
+
+ if (!compare)
+ split_values[i] = mtokval;
+ else if (split_values[i] != mtokval)
+ {
+ msg (SE, _("Expecting value %g for %s."),
+ split_values[i], dict_get_split_vars (default_dict)[i]->name);
+ return 0;
+ }
+ }
return 1;
}
for (j = 0; j < n_continuous; j++)
{
- temp_case->data[(default_dict.var
- [first_continuous + j]->fv)].f = *cp;
- debug_printf (("c:%s(%g) ",
- default_dict.var[first_continuous + j]->name,
- *cp));
+ int fv = dict_get_var (default_dict, first_continuous + j)->fv;
+ temp_case->data[fv].f = *cp;
cp++;
}
if (type == 1)
st_bare_pad_copy (temp_case->data[varname_->fv].s,
- default_dict.var[first_continuous + i]->name,
+ dict_get_var (default_dict,
+ first_continuous + i)->name,
8);
- debug_printf (("\n"));
write_case ();
}
}
nr_output_data (void)
{
{
- int i;
+ struct variable *const *split;
+ size_t split_cnt;
+ size_t i;
- for (i = 0; i < default_dict.n_splits; i++)
- temp_case->data[default_dict.splits[i]->fv].f = split_values[i];
+ split_cnt = dict_get_split_cnt (default_dict);
+ for (i = 0; i < split_cnt; i++)
+ temp_case->data[split[i]->fv].f = split_values[i];
}
if (n_factors)
wr_read_splits (void)
{
int compare;
-
- if (default_dict.n_splits == 0)
+ size_t split_cnt;
+
+ split_cnt = dict_get_split_cnt (default_dict);
+ if (split_cnt == 0)
return 1;
if (split_values)
else
{
compare = 0;
- split_values = xmalloc (sizeof *split_values * default_dict.n_splits);
+ split_values = xmalloc (split_cnt * sizeof *split_values);
}
{
int different = 0;
+ size_t split_cnt;
int i;
-
- for (i = 0; i < default_dict.n_splits; i++)
+
+ for (i = 0; i < split_cnt; i++)
{
if (!mget_token ())
return 0;
wr_output_data (void)
{
{
- int i;
+ struct variable *const *split;
+ size_t split_cnt;
+ size_t i;
- for (i = 0; i < default_dict.n_splits; i++)
- temp_case->data[default_dict.splits[i]->fv].f = split_values[i];
+ split_cnt = dict_get_split_cnt (default_dict);
+ for (i = 0; i < split_cnt; i++)
+ temp_case->data[split[i]->fv].f = split_values[i];
}
/* Sort the wr_data list. */
if (mtoken != MNUM)
{
msg (SE, _("Syntax error expecting value for %s %s."),
- default_dict.var[first_continuous + j]->name, context ());
+ dict_get_var (default_dict, first_continuous + j)->name,
+ context ());
return 0;
}
02111-1307, USA. */
#include <config.h>
+#include "matrix.h"
#include <assert.h>
#include <stdlib.h>
#include "alloc.h"
-#include "matrix.h"
\f
/* Kahan summation formula, Thm. 8, _What Every Computer Scientist
Should Know About Floating-Point Arithmetic_, David Goldberg,
return success;
}
-/* Returns nonzero only if value V is valid as an endpoint for a
- dependent variable in integer mode. */
-int
-validate_dependent_endpoint (double V)
-{
- return V == (int) V && V != LOWEST && V != HIGHEST;
-}
-
/* Parses the TABLES subcommand. */
static int
mns_custom_tables (struct cmd_means *cmd)
{
- struct dictionary *dict;
- struct dictionary temp_dict;
+ struct var_set *var_set;
if (!lex_match_id ("TABLES")
- && (token != T_ID || !is_varname (tokid))
+ && (token != T_ID || dict_lookup_var (default_dict, tokid) == NULL)
&& token != T_ALL)
return 2;
lex_match ('=');
return 0;
}
- if (cmd->sbc_variables)
- {
- dict = &temp_dict;
- temp_dict.var = v_var;
- temp_dict.nvar = n_var;
-
- {
- int i;
-
- temp_dict.name_tab = hsh_create (8, compare_variables, hash_variable,
- NULL, NULL);
- for (i = 0; i < temp_dict.nvar; i++)
- hsh_force_insert (temp_dict.name_tab, temp_dict.var[i]);
- }
- }
+ if (cmd->sbc_variables)
+ var_set = var_set_create_from_array (v_var, n_var);
else
- dict = &default_dict;
+ var_set = var_set_create_from_dict (default_dict);
+ assert (var_set != NULL);
do
{
int nvl;
struct variable **vl;
-
- if (!parse_variables (dict, &vl, &nvl, PV_NO_DUPLICATE | PV_NO_SCRATCH))
- return 0;
+
+ if (!parse_var_set_vars (var_set, &vl, &nvl,
+ PV_NO_DUPLICATE | PV_NO_SCRATCH))
+ goto lossage;
n_dim++;
nv_dim = xrealloc (nv_dim, n_dim * sizeof (int));
"CROSSBREAK, but not specified on "
"VARIABLES."),
v_dim[0][i]->name);
- return 0;
+ goto lossage;
}
if (n_dim == 1)
msg (SE, _("LOWEST and HIGHEST may not be used "
"for independent variables (%s)."),
v_dim[0][i]->name);
- return 0;
+ goto lossage;
}
if (v_inf->min != (int) v_inf->min
|| v_inf->max != (int) v_inf->max)
"have noninteger endpoints in their "
"ranges."),
v_dim[0][i]->name);
- return 0;
+ goto lossage;
}
}
}
}
while (lex_match (T_BY));
- /* Check for duplicates. */
- {
- int i;
-
- for (i = 0; i < default_dict.nvar; i++)
- default_dict.var[i]->foo = 0;
- for (i = 0; i < dict->nvar; i++)
- if (dict->var[i]->foo++)
- {
- msg (SE, _("Variable %s is multiply specified on TABLES "
- "or CROSSBREAK."),
- dict->var[i]->name);
- return 0;
- }
- }
-
- if (cmd->sbc_variables)
- hsh_destroy (temp_dict.name_tab);
-
+ var_set_destroy (var_set);
return 1;
+
+ lossage:
+ var_set_destroy (var_set);
+ return 0;
}
/* Parse CROSSBREAK subcommand. */
{
int i;
- for (i = 0; i < default_dict.nvar; i++)
- default_dict.var[i]->p.mns.min = SYSMIS;
+ for (i = 0; i < dict_get_var_cnt (default_dict); i++)
+ dict_get_var (default_dict, i)->p.mns.min = SYSMIS;
}
do
double min, max;
- if (!parse_variables (&default_dict, &v_var, &n_var,
+ if (!parse_variables (default_dict, &v_var, &n_var,
PV_APPEND | PV_NO_DUPLICATE | PV_NO_SCRATCH))
return 0;
{
int i;
- if (!parse_variables (NULL, &v, &nv, PV_SAME_TYPE))
+ if (!parse_variables (default_dict, &v, &nv, PV_SAME_TYPE))
return 0;
if (!lex_match ('('))
{
int positional; /* 1=POSITIONAL, 0=ALPHA. */
};
+/* Increasing order of variable index. */
+static struct ordering forward_positional_ordering = {1, 1};
+
static int compare_variables_given_ordering (const void *, const void *,
void *ordering);
-/* Explains how to modify the variables in a dictionary in conjunction
- with the p.mfv field of `variable'. */
+/* Explains how to modify the variables in a dictionary. */
struct var_modification
{
- /* REORDER information. */
- struct variable **reorder_list;
-
- /* RENAME information. */
- struct variable **old_names;
- char **new_names;
- int n_rename;
+ /* New variable ordering. */
+ struct variable **reorder_vars;
+ size_t reorder_cnt;
/* DROP/KEEP information. */
- int n_drop; /* Number of variables being dropped. */
+ struct variable **drop_vars;
+ size_t drop_cnt;
+
+ /* New variable names. */
+ struct variable **rename_vars;
+ char **new_names;
+ size_t rename_cnt;
};
-static struct dictionary *rearrange_dict (struct dictionary *d,
- struct var_modification *vm,
- int permanent);
+static int rearrange_dict (struct dictionary *d,
+ const struct var_modification *vm);
/* Performs MODIFY VARS command. */
int
/* What we're gonna do to the active file. */
struct var_modification vm;
+ /* Return code. */
+ int ret_code = CMD_FAILURE;
+
+ size_t i;
+
lex_match_id ("MODIFY");
lex_match_id ("VARS");
- vm.reorder_list = NULL;
- vm.old_names = NULL;
+ vm.reorder_vars = NULL;
+ vm.reorder_cnt = 0;
+ vm.rename_vars = NULL;
vm.new_names = NULL;
- vm.n_rename = 0;
- vm.n_drop = 0;
+ vm.rename_cnt = 0;
+ vm.drop_vars = NULL;
+ vm.drop_cnt = 0;
/* Parse each subcommand. */
lex_match ('/');
if (already_encountered & 1)
{
msg (SE, _("REORDER subcommand may be given at most once."));
- goto lossage;
+ goto done;
}
already_encountered |= 1;
{
msg (SE, _("Cannot specify ALL after specifying a set "
"of variables."));
- goto lossage;
+ goto done;
}
- fill_all_vars (&v, &nv, FV_NO_SYSTEM);
+ dict_get_vars (default_dict, &v, &nv, 1u << DC_SYSTEM);
}
else
{
{
msg (SE, _("`(' expected on REORDER subcommand."));
free (v);
- goto lossage;
+ goto done;
}
- if (!parse_variables (&default_dict, &v, &nv,
+ if (!parse_variables (default_dict, &v, &nv,
PV_APPEND | PV_NO_DUPLICATE))
{
free (v);
- goto lossage;
+ goto done;
}
if (!lex_match (')'))
{
msg (SE, _("`)' expected following variable names on "
"REORDER subcommand."));
free (v);
- goto lossage;
+ goto done;
}
}
sort (&v[prev_nv], nv - prev_nv, sizeof *v,
}
while (token != '/' && token != '.');
- if (nv != default_dict.nvar)
- {
- size_t nbytes = DIV_RND_UP (default_dict.nvar, 8);
- unsigned char *bits = local_alloc (nbytes);
- int i;
-
- memset (bits, 0, nbytes);
- for (i = 0; i < nv; i++)
- SET_BIT (bits, v[i]->index);
- v = xrealloc (v, sizeof *v * default_dict.nvar);
- for (i = 0; i < default_dict.nvar; i++)
- if (!TEST_BIT (bits, i))
- v[nv++] = default_dict.var[i];
- local_free (bits);
- }
-
- vm.reorder_list = v;
+ vm.reorder_vars = v;
+ vm.reorder_cnt = nv;
}
else if (lex_match_id ("RENAME"))
{
if (already_encountered & 2)
{
msg (SE, _("RENAME subcommand may be given at most once."));
- goto lossage;
+ goto done;
}
already_encountered |= 2;
lex_match ('=');
do
{
- int prev_nv_1 = vm.n_rename;
- int prev_nv_2 = vm.n_rename;
+ int prev_nv_1 = vm.rename_cnt;
+ int prev_nv_2 = vm.rename_cnt;
if (!lex_match ('('))
{
msg (SE, _("`(' expected on RENAME subcommand."));
- goto lossage;
+ goto done;
}
- if (!parse_variables (&default_dict, &vm.old_names, &vm.n_rename,
+ if (!parse_variables (default_dict, &vm.rename_vars, &vm.rename_cnt,
PV_APPEND | PV_NO_DUPLICATE))
- goto lossage;
+ goto done;
if (!lex_match ('='))
{
msg (SE, _("`=' expected between lists of new and old variable "
"names on RENAME subcommand."));
- goto lossage;
+ goto done;
}
if (!parse_DATA_LIST_vars (&vm.new_names, &prev_nv_1, PV_APPEND))
- goto lossage;
- if (prev_nv_1 != vm.n_rename)
+ goto done;
+ if (prev_nv_1 != vm.rename_cnt)
{
- int i;
-
msg (SE, _("Differing number of variables in old name list "
"(%d) and in new name list (%d)."),
- vm.n_rename - prev_nv_2, prev_nv_1 - prev_nv_2);
+ vm.rename_cnt - prev_nv_2, prev_nv_1 - prev_nv_2);
for (i = 0; i < prev_nv_1; i++)
- free (&vm.new_names[i]);
- free (&vm.new_names);
+ free (vm.new_names[i]);
+ free (vm.new_names);
vm.new_names = NULL;
- goto lossage;
+ goto done;
}
if (!lex_match (')'))
{
msg (SE, _("`)' expected after variable lists on RENAME "
"subcommand."));
- goto lossage;
+ goto done;
}
}
while (token != '.' && token != '/');
}
else if (lex_match_id ("KEEP"))
{
- struct ordering ordering;
- struct variable **keep_vars;
- int nv;
- int counter;
- int i;
+ struct variable **keep_vars, **all_vars, **drop_vars;
+ int keep_cnt, all_cnt, drop_cnt;
if (already_encountered & 4)
{
msg (SE, _("KEEP subcommand may be given at most once. It may not"
"be given in conjunction with the DROP subcommand."));
- goto lossage;
+ goto done;
}
already_encountered |= 4;
lex_match ('=');
- if (!parse_variables (&default_dict, &keep_vars, &nv, PV_NONE))
- goto lossage;
+ if (!parse_variables (default_dict, &keep_vars, &keep_cnt, PV_NONE))
+ goto done;
/* Transform the list of variables to keep into a list of
variables to drop. First sort the keep list, then figure
out which variables are missing. */
- ordering.forward = ordering.positional = 1;
- sort (keep_vars, nv, sizeof *keep_vars,
- compare_variables_given_ordering, &ordering);
-
- vm.n_drop = default_dict.nvar - nv;
-
- counter = 0;
- for (i = 0; i < nv; i++)
- {
- while (counter < keep_vars[i]->index)
- default_dict.var[counter++]->p.mfv.drop_this_var = 1;
- default_dict.var[counter++]->p.mfv.drop_this_var = 0;
- }
- while (counter < nv)
- default_dict.var[counter++]->p.mfv.drop_this_var = 1;
-
- free (keep_vars);
+ sort (keep_vars, keep_cnt, sizeof *keep_vars,
+ compare_variables_given_ordering, &forward_positional_ordering);
+
+ dict_get_vars (default_dict, &all_vars, &all_cnt, 0);
+
+ drop_cnt = all_cnt - keep_cnt;
+ drop_vars = xmalloc (drop_cnt * sizeof *keep_vars);
+ if (set_difference (all_vars, all_cnt,
+ keep_vars, keep_cnt,
+ sizeof *all_vars,
+ drop_vars,
+ compare_variables_given_ordering,
+ &forward_positional_ordering)
+ != drop_cnt)
+ assert (0);
+
+ free (keep_vars);
+ free (all_vars);
+
+ vm.drop_vars = drop_vars;
+ vm.drop_cnt = drop_cnt;
}
else if (lex_match_id ("DROP"))
{
struct variable **drop_vars;
- int nv;
- int i;
+ int drop_cnt;
if (already_encountered & 4)
{
- msg (SE, _("DROP subcommand may be given at most once. It may not"
- "be given in conjunction with the KEEP subcommand."));
- goto lossage;
+ msg (SE, _("DROP subcommand may be given at most once. It may "
+ "not be given in conjunction with the KEEP "
+ "subcommand."));
+ goto done;
}
already_encountered |= 4;
lex_match ('=');
- if (!parse_variables (&default_dict, &drop_vars, &nv, PV_NONE))
- goto lossage;
- for (i = 0; i < default_dict.nvar; i++)
- default_dict.var[i]->p.mfv.drop_this_var = 0;
- for (i = 0; i < nv; i++)
- drop_vars[i]->p.mfv.drop_this_var = 1;
- vm.n_drop = nv;
- free (drop_vars);
+ if (!parse_variables (default_dict, &drop_vars, &drop_cnt, PV_NONE))
+ goto done;
+ vm.drop_vars = drop_vars;
+ vm.drop_cnt = drop_cnt;
}
else if (lex_match_id ("MAP"))
{
- struct dictionary *new_dict = rearrange_dict (&default_dict, &vm, 0);
- if (!new_dict)
- goto lossage;
- /* FIXME: display new dictionary. */
+ struct dictionary *temp = dict_clone (default_dict);
+ int success = rearrange_dict (temp, &vm);
+ if (success)
+ {
+ /* FIXME: display new dictionary. */
+ }
+ dict_destroy (temp);
}
else
{
msg (SE, _("Unrecognized subcommand name `%s'."), tokid);
else
msg (SE, _("Subcommand name expected."));
- goto lossage;
+ goto done;
}
if (token == '.')
if (token != '/')
{
msg (SE, _("`/' or `.' expected."));
- goto lossage;
+ goto done;
}
lex_get ();
}
- {
- int i;
-
- if (already_encountered & (1 | 4))
- {
- /* Read the data. */
- procedure (NULL, NULL, NULL);
- }
-
- if (NULL == rearrange_dict (&default_dict, &vm, 1))
- goto lossage;
+ if (already_encountered & (1 | 4))
+ {
+ /* Read the data. */
+ procedure (NULL, NULL, NULL);
+ }
- free (vm.reorder_list);
- free (vm.old_names);
- for (i = 0; i < vm.n_rename; i++)
- free (vm.new_names[i]);
- free (vm.new_names);
+ if (!rearrange_dict (default_dict, &vm))
+ goto done;
- return CMD_SUCCESS;
- }
+ ret_code = CMD_SUCCESS;
-lossage:
- {
- int i;
-
- free (vm.reorder_list);
- free (vm.old_names);
- for (i = 0; i < vm.n_rename; i++)
- free (vm.new_names[i]);
- free (vm.new_names);
- return CMD_FAILURE;
- }
+done:
+ free (vm.reorder_vars);
+ free (vm.rename_vars);
+ for (i = 0; i < vm.rename_cnt; i++)
+ free (vm.new_names[i]);
+ free (vm.new_names);
+ free (vm.drop_vars);
+ return ret_code;
}
/* Compares A and B according to the settings in
return result;
}
-/* (Possibly) rearranges variables and (possibly) removes some
- variables and (possibly) renames some more variables in dictionary
- D. There are two modes of operation, distinguished by the value of
- PERMANENT:
-
- If PERMANENT is nonzero, then the dictionary is modified in place.
- Returns the new dictionary on success or NULL if there would have
- been duplicate variable names in the resultant dictionary (in this
- case the dictionary has not been modified).
-
- If PERMANENT is zero, then the dictionary is copied to a new
- dictionary structure that retains most of the same deep structure
- as D. The p.mfv.new_name field of each variable is set to what
- would become the variable's new name if PERMANENT were nonzero.
- Returns the new dictionary. */
-static struct dictionary *
-rearrange_dict (struct dictionary * d, struct var_modification * vm, int permanent)
-{
- struct dictionary *n;
-
- struct variable **save_var;
+/* Pairs a variable with a new name. */
+struct var_renaming
+ {
+ struct variable *var;
+ char new_name[9];
+ };
- /* Linked list of variables for deletion. */
- struct variable *head, *tail;
+/* A algo_compare_func that compares new_name members in struct
+ var_renaming structures A and B. */
+static int
+compare_var_renaming_by_new_name (const void *a_, const void *b_,
+ void *foo unused)
+{
+ const struct var_renaming *a = a_;
+ const struct var_renaming *b = b_;
- int i;
+ return strcmp (a->new_name, b->new_name);
+}
- /* First decide what dictionary to modify. */
- if (permanent == 0)
+/* Returns true if performing VM on dictionary D would not cause
+ problems such as duplicate variable names. Returns false
+ otherwise, and issues an error message. */
+static int
+validate_var_modification (const struct dictionary *d,
+ const struct var_modification *vm)
+{
+ /* Variable reordering can't be a problem, so we don't simulate
+ it. Variable renaming can cause duplicate names, but
+ dropping variables can eliminate them, so we simulate both
+ of those. */
+ struct variable **all_vars;
+ struct variable **keep_vars;
+ struct variable **drop_vars;
+ size_t all_cnt, keep_cnt, drop_cnt;
+
+ struct var_renaming *var_renaming;
+ int valid;
+ size_t i;
+
+ /* All variables, in index order. */
+ dict_get_vars (d, &all_vars, &all_cnt, 0);
+
+ /* Drop variables, in index order. */
+ drop_cnt = vm->drop_cnt;
+ drop_vars = xmalloc (drop_cnt * sizeof *drop_vars);
+ memcpy (drop_vars, vm->drop_vars, drop_cnt * sizeof *drop_vars);
+ sort (drop_vars, drop_cnt, sizeof *drop_vars,
+ compare_variables_given_ordering, &forward_positional_ordering);
+
+ /* Keep variables, in index order. */
+ keep_cnt = all_cnt - drop_cnt;
+ keep_vars = xmalloc (keep_cnt * sizeof *keep_vars);
+ if (set_difference (all_vars, all_cnt,
+ drop_vars, drop_cnt,
+ sizeof *all_vars,
+ keep_vars,
+ compare_variables_given_ordering,
+ &forward_positional_ordering) != keep_cnt)
+ assert (0);
+
+ /* Copy variables into var_renaming array. */
+ var_renaming = xmalloc (keep_cnt * sizeof *var_renaming);
+ for (i = 0; i < keep_cnt; i++)
{
- n = xmalloc (sizeof *n);
- *n = *d;
+ var_renaming[i].var = keep_vars[i];
+ strcpy (var_renaming[i].new_name, keep_vars[i]->name);
}
- else
- n = d;
- save_var = n->var;
-
- /* Perform first half of renaming. */
- if (permanent)
+
+ /* Rename variables in var_renaming array. */
+ for (i = 0; i < vm->rename_cnt; i++)
{
- for (i = 0; i < d->nvar; i++)
- d->var[i]->p.mfv.new_name[0] = 0;
- d->var = xmalloc (sizeof *d->var * d->nvar);
+ struct variable *const *kv;
+ struct var_renaming *vr;
+
+ /* Get the var_renaming element. */
+ kv = binary_search (keep_vars, keep_cnt, sizeof *keep_vars,
+ &vm->rename_vars[i],
+ compare_variables_given_ordering,
+ &forward_positional_ordering);
+ if (kv == NULL)
+ continue;
+ vr = var_renaming + (kv - keep_vars);
+
+ strcpy (vr->new_name, vm->new_names[i]);
}
- else
- for (i = 0; i < d->nvar; i++)
- strcpy (d->var[i]->p.mfv.new_name, d->var[i]->name);
- for (i = 0; i < vm->n_rename; i++)
- strcpy (vm->old_names[i]->p.mfv.new_name, vm->new_names[i]);
-
- /* Copy the variable list, reordering if appropriate. */
- if (vm->reorder_list)
- memcpy (n->var, vm->reorder_list, sizeof *n->var * d->nvar);
- else if (!permanent)
- for (i = 0; i < d->nvar; i++)
- n->var[i] = d->var[i];
-
- /* Drop all the unwanted variables. */
- head = NULL;
- if (vm->n_drop)
- {
- int j;
- n->nvar = d->nvar - vm->n_drop;
- for (i = j = 0; i < n->nvar; i++)
- {
- while (n->var[j]->p.mfv.drop_this_var != 0)
- {
- if (permanent)
- {
- /* If this is permanent, then we have to keep a list
- of all the dropped variables because they must be
- free()'d, but can't be until we know that there
- aren't any duplicate variable names. */
- if (head)
- tail = tail->p.mfv.next = n->var[j];
- else
- head = tail = n->var[j];
- }
- j++;
- }
- n->var[i] = n->var[j++];
- }
- if (permanent)
- tail->p.mfv.next = NULL;
- }
+ /* Sort var_renaming array by new names and check for
+ duplicates. */
+ sort (var_renaming, keep_cnt, sizeof *var_renaming,
+ compare_var_renaming_by_new_name, NULL);
+ valid = adjacent_find_equal (var_renaming, keep_cnt, sizeof *var_renaming,
+ compare_var_renaming_by_new_name, NULL) == NULL;
- /* Check for duplicate variable names if appropriate. */
- if (permanent && vm->n_rename)
- {
- struct ordering ordering;
- struct variable **v;
+ /* Clean up. */
+ free (all_vars);
+ free (keep_vars);
+ free (drop_vars);
+ free (var_renaming);
- if (vm->reorder_list)
- v = vm->reorder_list; /* Reuse old buffer if possible. */
- else
- v = xmalloc (sizeof *v * n->nvar);
- memcpy (v, n->var, sizeof *v * n->nvar);
- ordering.forward = 1;
- ordering.positional = 0;
- sort (v, n->nvar, sizeof *v,
- compare_variables_given_ordering, &ordering);
- for (i = 1; i < n->nvar; i++)
- if (!strcmp (n->var[i]->name, n->var[i - 1]->name))
- {
- msg (SE, _("Duplicate variable name `%s' after renaming."),
- n->var[i]->name);
- if (vm->reorder_list == NULL)
- free (v);
- n->var = save_var;
- return NULL;
- }
- if (vm->reorder_list == NULL)
- free (v);
- }
+ return valid;
+}
- /* Delete unwanted variables and finalize renaming if
- appropriate. */
- if (permanent)
+/* Reoders, removes, and renames variables in dictionary D
+ according to VM. Returns nonzero if successful, zero if there
+ would have been duplicate variable names if the modifications
+ had been carried out. In the latter case, the dictionary is
+ not modified. */
+static int
+rearrange_dict (struct dictionary *d, const struct var_modification *vm)
+{
+ char **rename_old_names;
+
+ struct variable **rename_vars;
+ char **rename_new_names;
+ size_t rename_cnt;
+
+ size_t i;
+
+ /* Check whether the modifications will cause duplicate
+ names. */
+ if (!validate_var_modification (d, vm))
+ return 0;
+
+ /* Record the old names of variables to rename. After
+ variables are deleted, we can't depend on the variables to
+ still exist, but we can still look them up by name. */
+ rename_old_names = xmalloc (vm->rename_cnt * sizeof *rename_old_names);
+ for (i = 0; i < vm->rename_cnt; i++)
+ rename_old_names[i] = xstrdup (vm->rename_vars[i]->name);
+
+ /* Reorder and delete variables. */
+ dict_reorder_vars (d, vm->reorder_vars, vm->reorder_cnt);
+ dict_delete_vars (d, vm->drop_vars, vm->drop_cnt);
+
+ /* Compose lists of variables to rename and their new names. */
+ rename_vars = xmalloc (vm->rename_cnt * sizeof *rename_vars);
+ rename_new_names = xmalloc (vm->rename_cnt * sizeof *rename_new_names);
+ rename_cnt = 0;
+ for (i = 0; i < vm->rename_cnt; i++)
{
- /* Delete dropped variables for good. */
- for (; head; head = tail)
- {
- tail = head->p.mfv.next;
- clear_variable (n, head);
- free (head);
- }
+ struct variable *var = dict_lookup_var (d, rename_old_names[i]);
+ if (var == NULL)
+ continue;
+
+ rename_vars[rename_cnt] = var;
+ rename_new_names[rename_cnt] = vm->new_names[i];
+ rename_cnt++;
+ }
- /* Remove names from all renamed variables. */
- head = NULL;
- for (i = 0; i < n->nvar; i++)
- if (n->var[i]->p.mfv.new_name[0])
- {
- hsh_force_delete (n->name_tab, n->var[i]);
- if (head)
- tail = tail->p.mfv.next = n->var[i];
- else
- head = tail = n->var[i];
- }
- if (head)
- tail->p.mfv.next = NULL;
-
- /* Put names onto renamed variables. */
- for (; head; head = head->p.mfv.next)
- {
- strcpy (head->name, head->p.mfv.new_name);
- hsh_force_insert (n->name_tab, head);
- }
- free (save_var);
+ /* Do renaming. */
+ if (dict_rename_vars (d, rename_vars, rename_new_names, rename_cnt,
+ NULL) == 0)
+ assert (0);
- /* As a final step the index fields must be redone. */
- for (i = 0; i < n->nvar; i++)
- n->var[i]->index = i;
- }
+ /* Clean up. */
+ for (i = 0; i < vm->rename_cnt; i++)
+ free (rename_old_names[i]);
+ free (rename_old_names);
+ free (rename_vars);
+ free (rename_new_names);
- return n;
+ return 1;
}
/* Create each variable. */
for (i = 0; i < nv; i++)
{
- struct variable *new_var = create_variable (&default_dict, v[i],
- NUMERIC, 0);
+ struct variable *new_var = dict_create_var (default_dict, v[i], 0);
if (!new_var)
msg (SE, _("There is already a variable named %s."), v[i]);
else
/* Create each variable. */
for (i = 0; i < nv; i++)
{
- struct variable *new_var = create_variable (&default_dict, v[i],
- ALPHA, width);
+ struct variable *new_var = dict_create_var (default_dict, v[i],
+ width);
if (!new_var)
msg (SE, _("There is already a variable named %s."), v[i]);
else
int i;
lex_match_id ("LEAVE");
- if (!parse_variables (NULL, &v, &nv, PV_NONE))
+ if (!parse_variables (default_dict, &v, &nv, PV_NONE))
return CMD_FAILURE;
for (i = 0; i < nv; i++)
{
02111-1307, USA. */
#include <config.h>
+#include "output.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include "filename.h"
#include "lexer.h"
#include "misc.h"
-#include "output.h"
#include "settings.h"
#include "str.h"
/* Looks for a macro with key KEY, and returns the corresponding value
if found, or NULL if not. */
-const char *
+static const char *
find_defn_value (const char *key)
{
static char buf[INT_DIGITS + 1];
/* Destroys all the drivers in driver list *DL and sets *DL to
NULL. */
-void
+static void
destroy_list (struct outp_driver ** dl)
{
struct outp_driver *d, *next;
#endif
#endif
+#include "pfm.h"
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include "hash.h"
#include "magic.h"
#include "misc.h"
-#include "pfm.h"
#include "str.h"
#include "value-labels.h"
#include "var.h"
fclose (ext->file);
if (ext && ext->dict)
- free_dictionary (ext->dict);
+ dict_destroy (ext->dict);
free (ext);
h->class = NULL;
h->ext = NULL;
}
/* Read an integer and return its value, or NOT_INT on failure. */
-int
+static int
read_int (struct file_handle *h)
{
double f = read_float (h);
read_variables (struct file_handle *h)
{
struct pfm_fhuser_ext *ext = h->ext;
+ char *weight_name = NULL;
int i;
if (!match (68 /* 4 */))
corrupt_msg (h, _("Unexpected flag value %d."), x);
}
- ext->dict = new_dictionary (0);
+ ext->dict = dict_create ();
if (match (70 /* 6 */))
{
- char *name = read_string (h);
- if (!name)
+ weight_name = read_string (h);
+ if (!weight_name)
goto lossage;
- strcpy (ext->dict->weight_var, name);
- asciify (ext->dict->weight_var);
+ asciify (weight_name);
+ if (strlen (weight_name) > 8)
+ {
+ corrupt_msg (h, _("Weight variable name (%s) truncated."),
+ weight_name);
+ weight_name[8] = '\0';
+ }
}
for (i = 0; i < ext->nvars; i++)
if (width < 0 || width > 255)
lose ((h, "Bad width %d for variable %s.", width, name));
- v = create_variable (ext->dict, name, width ? ALPHA : NUMERIC, width);
+ v = dict_create_var (ext->dict, name, width);
v->get.fv = v->fv;
if (v == NULL)
lose ((h, _("Duplicate variable name %s."), name));
asciify (v->label);
}
}
- ext->case_size = ext->dict->nval;
- if (ext->dict->weight_var[0] != 0
- && !find_dict_variable (ext->dict, ext->dict->weight_var))
- lose ((h, _("Weighting variable %s not present in dictionary."),
- ext->dict->weight_var));
+ if (weight_name != NULL)
+ {
+ struct variable *weight_var = dict_lookup_var (ext->dict, weight_name);
+ if (weight_var == NULL)
+ lose ((h, _("Weighting variable %s not present in dictionary."),
+ weight_name));
+ free (weight_name);
+
+ dict_set_weight (ext->dict, weight_var);
+ }
return 1;
lossage:
+ free (weight_name);
return 0;
}
goto lossage;
asciify (name);
- v[i] = find_dict_variable (ext->dict, name);
+ v[i] = dict_lookup_var (ext->dict, name);
if (v[i] == NULL)
lose ((h, _("Unknown variable %s while parsing value labels."), name));
/* Translate a case in data file format to a case in active file
format. */
- for (i = 0; i < dict->nvar; i++)
+ for (i = 0; i < dict_get_var_cnt (dict); i++)
{
- struct variable *v = dict->var[i];
+ struct variable *v = dict_get_var (dict, i);
if (v->get.fv == -1)
continue;
02111-1307, USA. */
#include <config.h>
+#include "pfm.h"
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include "gmp.h"
#include "hash.h"
#include "magic.h"
-#include "pfm.h"
#include "str.h"
#include "value-labels.h"
#include "var.h"
{
int i;
- ext->nvars = dict->nvar;
- ext->vars = xmalloc (sizeof *ext->vars * dict->nvar);
- for (i = 0; i < dict->nvar; i++)
- ext->vars[i] = dict->var[i]->width;
+ ext->nvars = dict_get_var_cnt (dict);
+ ext->vars = xmalloc (sizeof *ext->vars * ext->nvars);
+ for (i = 0; i < ext->nvars; i++)
+ ext->vars[i] = dict_get_var (dict, i)->width;
}
/* Write the file header. */
{
int i;
- if (!bufwrite (h, "4", 1) || !write_int (h, dict->nvar)
+ if (!bufwrite (h, "4", 1) || !write_int (h, dict_get_var_cnt (dict))
|| !write_int (h, 161))
return 0;
- for (i = 0; i < dict->nvar; i++)
+ for (i = 0; i < dict_get_var_cnt (dict); i++)
{
static const char *miss_types[MISSING_COUNT] =
{
const char *m;
int j;
- struct variable *v = dict->var[i];
+ struct variable *v = dict_get_var (dict, i);
if (!bufwrite (h, "7", 1) || !write_int (h, v->width)
|| !write_string (h, v->name)
{
int i;
- for (i = 0; i < dict->nvar; i++)
+ for (i = 0; i < dict_get_var_cnt (dict); i++)
{
struct val_labs_iterator *j;
- struct variable *v = dict->var[i];
+ struct variable *v = dict_get_var (dict, i);
struct val_lab *vl;
if (!val_labs_count (v->val_labs))
struct dictionary *pfm_read_dictionary (struct file_handle *,
struct pfm_read_info *);
-int pfm_read_case (struct file_handle *, union value *, struct dictionary *);
+int pfm_read_case (struct file_handle *,
+ union value *, struct dictionary *);
int pfm_write_dictionary (struct file_handle *, struct dictionary *);
int pfm_write_case (struct file_handle *, const union value *elem);
#if HAVE_CONFIG_H
#include <config.h>
#endif
+#include "pool.h"
#include <assert.h>
#include <stdlib.h>
#include "alloc.h"
-#include "pool.h"
#include "str.h"
/* Fast, low-overhead memory block suballocator. */
\f
/* Driver initialization. */
-int
+static int
ps_open_global (struct outp_class *this unused)
{
init_fonts ();
return 1;
}
-int
+static int
ps_close_global (struct outp_class *this unused)
{
return 1;
}
-int *
+static int *
ps_font_sizes (struct outp_class *this unused, int *n_valid_sizes)
{
/* Allow fonts up to 1" in height. */
return valid_sizes;
}
-int
+static int
ps_preopen_driver (struct outp_driver *this)
{
struct ps_driver_ext *x;
return 1;
}
-int
+static int
ps_postopen_driver (struct outp_driver *this)
{
struct ps_driver_ext *x = this->ext;
return 1;
}
-int
+static int
ps_close_driver (struct outp_driver *this)
{
struct ps_driver_ext *x = this->ext;
};
static struct outp_option_info option_info;
-void
+static void
ps_option (struct outp_driver *this, const char *key, const struct string *val)
{
struct ps_driver_ext *x = this->ext;
return 1;
}
-int
+static int
ps_open_page (struct outp_driver *this)
{
struct ps_driver_ext *x = this->ext;
return !ferror (x->file.file);
}
-int
+static int
ps_close_page (struct outp_driver *this)
{
struct ps_driver_ext *x = this->ext;
(*f)->ndep++;
}
-void
+static void
ps_line_horz (struct outp_driver *this, const struct rect *r,
const struct color *c unused, int style)
{
line (this, style, y, r->x1, r->x2);
}
-void
+static void
ps_line_vert (struct outp_driver *this, const struct rect *r,
const struct color *c unused, int style)
{
#define T (style->t != OUTP_L_NONE)
#define B (style->b != OUTP_L_NONE)
-void
+static void
ps_line_intersection (struct outp_driver *this, const struct rect *r,
const struct color *c unused,
const struct outp_styles *style)
}
}
-void
-ps_line_width (struct outp_driver *this, int *width, int *height)
-{
- struct ps_driver_ext *x = this->ext;
-
- assert (this->driver_open && this->page_open);
- width[0] = height[0] = 0;
- width[1] = height[1] = 2 * x->line_gutter + x->line_width;
- width[2] = height[2] = (2 * x->line_gutter + 2 * x->line_width
- + x->line_space);
- width[3] = height[3] = 2 * x->line_gutter + x->line_width;
-}
-
-void
+static void
ps_box (struct outp_driver *this unused, const struct rect *r unused,
const struct color *bord unused, const struct color *fill unused)
{
assert (this->driver_open && this->page_open);
}
-void
+static void
ps_polyline_begin (struct outp_driver *this unused,
const struct color *c unused)
{
assert (this->driver_open && this->page_open);
}
-void
+static void
ps_polyline_point (struct outp_driver *this unused, int x unused, int y unused)
{
assert (this->driver_open && this->page_open);
}
-void
+static void
ps_polyline_end (struct outp_driver *this unused)
{
assert (this->driver_open && this->page_open);
\f
/* Text. */
-void
+static void
ps_text_set_font_by_name (struct outp_driver *this, const char *dit)
{
struct ps_driver_ext *x = this->ext;
x->current = fe;
}
-void
+static void
ps_text_set_font_by_position (struct outp_driver *this, int pos)
{
struct ps_driver_ext *x = this->ext;
local_free (dit);
}
-void
+static void
ps_text_set_font_family (struct outp_driver *this, const char *s)
{
struct ps_driver_ext *x = this->ext;
x->family = xstrdup (s);
}
-const char *
+static const char *
ps_text_get_font_name (struct outp_driver *this)
{
struct ps_driver_ext *x = this->ext;
return x->current->font->name;
}
-const char *
+static const char *
ps_text_get_font_family (struct outp_driver *this)
{
struct ps_driver_ext *x = this->ext;
return x->family;
}
-int
+static int
ps_text_set_size (struct outp_driver *this, int size)
{
struct ps_driver_ext *x = this->ext;
return 1;
}
-int
+static int
ps_text_get_size (struct outp_driver *this, int *em_width)
{
struct ps_driver_ext *x = this->ext;
ext->size = old_size;
}
-void
+static void
ps_text_metrics (struct outp_driver *this, struct outp_text *t)
{
assert (this->driver_open && this->page_open);
text (this, t, 0);
}
-void
+static void
ps_text_draw (struct outp_driver *this, struct outp_text *t)
{
assert (this->driver_open && this->page_open);
static int
parse_variable_argument (void)
{
- if (!parse_variables (NULL, &fx.v, &fx.nv, PV_DUPLICATE))
+ if (!parse_variables (default_dict, &fx.v, &fx.nv, PV_DUPLICATE))
return 0;
if (token == T_NUM)
char nullstr[] = "";
/* Close all open files and delete the output file, on failure. */
-void
+static void
finish_up (void)
{
if (!is_open)
/* Allocate a block of SIZE bytes and return a pointer to its
beginning. */
-void *
+static void *
xmalloc (size_t size)
{
void *vp;
return vp;
}
-/* Resize the block at PTR to size SIZE and return a pointer to the
- beginning of the new block. */
-void *
-xrealloc (void *ptr, size_t size)
-{
- void *vp;
-
- if (!size)
- {
- if (ptr)
- free (ptr);
- return NULL;
- }
-
- if (ptr)
- vp = realloc (ptr, size);
- else
- vp = malloc (size);
-
- if (!vp)
- fail ("xrealloc(%lu): %s", (unsigned long) size, VME);
-
- return vp;
-}
-
/* Make a dynamically allocated copy of string S and return a pointer
to the first character. */
-char *
+static char *
xstrdup (const char *s)
{
size_t size;
/* Returns a pointer to one of 8 static buffers. The buffers are used
in rotation. */
-char *
+static char *
get_buffer (void)
{
static char b[8][256];
/* Copies a string to a static buffer, converting it to lowercase in
the process, and returns a pointer to the static buffer. */
-char *
+static char *
st_lower (const char *s)
{
char *p, *cp;
/* Copies a string to a static buffer, converting it to uppercase in
the process, and returns a pointer to the static buffer. */
-char *
+static char *
st_upper (const char *s)
{
char *p, *cp;
/* Returns the address of the first non-whitespace character in S, or
the address of the null terminator if none. */
-char *
+static char *
skip_ws (const char *s)
{
while (isspace ((unsigned char) *s))
/* Read one line from the input file into buf. Lines having special
formats are handled specially. */
-int
+static int
get_line (void)
{
ln++;
in the symbol table, its sequence number is returned and the symbol
table is not modified. Otherwise, the symbol is added and the next
available sequence number is returned. */
-int
+static int
add_symbol (const char *name, int unique, int value)
{
symbol *iter, *sym;
/* Finds the symbol having given sequence number X within the symbol
table, and returns the associated symbol structure. */
-symbol *
+static symbol *
find_symbol (int x)
{
symbol *iter;
#endif /* DEBUGGING */
/* Reads a token from the input file. */
-int
+static int
lex_get (void)
{
/* Skip whitespace and check for end of file. */
}
/* Force the current token to be an identifier token. */
-void
+static void
force_id (void)
{
if (token != T_ID)
}
/* Force the current token to be a string token. */
-void
+static void
force_string (void)
{
if (token != T_STRING)
/* Checks whether the current token is the identifier S; if so, skips
the token and returns 1; otherwise, returns 0. */
-int
+static int
match_id (const char *s)
{
if (token == T_ID && !strcmp (tokstr, s))
/* Checks whether the current token is T. If so, skips the token and
returns 1; otherwise, returns 0. */
-int
+static int
match_token (int t)
{
if (token == t)
}
/* Force the current token to be T, and skip it. */
-void
+static void
skip_token (int t)
{
if (token != t)
void parse_subcommands (void);
/* Parse an entire specification. */
-void
+static void
parse (void)
{
/* Get the command name and prefix. */
/* Parses a single setting into S, given subcommand information SBC
and specifier information SPEC. */
-void
+static void
parse_setting (setting *s, specifier *spec)
{
s->parent = spec;
/* Parse a single specifier into SPEC, given subcommand information
SBC. */
-void
+static void
parse_specifier (specifier *spec, subcommand *sbc)
{
spec->index = 0;
}
/* Parse a list of specifiers for subcommand SBC. */
-void
+static void
parse_specifiers (subcommand *sbc)
{
specifier **spec = &sbc->spec;
}
/* Parse a subcommand into SBC. */
-void
+static void
parse_subcommand (subcommand *sbc)
{
if (match_token ('*'))
/* Write the structure members for specifier SPEC to the output file.
SBC is the including subcommand. */
-void
+static void
dump_specifier_vars (const specifier *spec, const subcommand *sbc)
{
if (spec->varname)
}
/* Returns 1 if string T is a PSPP keyword, 0 otherwise. */
-int
+static int
is_keyword (const char *t)
{
static const char *kw[] =
/* Transforms a string NAME into a valid C identifier: makes
everything lowercase and maps nonalphabetic characters to
underscores. Returns a pointer to a static buffer. */
-char *
+static char *
make_identifier (const char *name)
{
char *p = get_buffer ();
}
/* Writes the struct and enum declarations for the parser. */
-void
+static void
dump_declarations (void)
{
indent = 0;
/* Writes out code to initialize all the variables that need
initialization for particular specifier SPEC inside subcommand SBC. */
-void
+static void
dump_specifier_init (const specifier *spec, const subcommand *sbc)
{
if (spec->varname)
}
/* Write code to initialize all variables. */
-void
+static void
dump_vars_init (void)
{
/* Loop through all the subcommands. */
/* Return a pointer to a static buffer containing an expression that
will match token T. */
-char *
+static char *
make_match (const char *t)
{
char *s;
/* Write out the parsing code for specifier SPEC within subcommand
SBC. */
-void
+static void
dump_specifier_parse (const specifier *spec, const subcommand *sbc)
{
setting *s;
}
/* Write out the code to parse subcommand SBC. */
-void
+static void
dump_subcommand (const subcommand *sbc)
{
if (sbc->type == SBC_PLAIN || sbc->type == SBC_ARRAY)
}
else if (sbc->type == SBC_VARLIST)
{
- dump (1, "if (!parse_variables (NULL, &p->%sv_%s, &p->%sn_%s, "
+ dump (1, "if (!parse_variables (default_dict, &p->%sv_%s, &p->%sn_%s, "
"PV_APPEND%s%s))",
st_lower (sbc->prefix), st_lower (sbc->name),
st_lower (sbc->prefix), st_lower (sbc->name),
}
/* Write out entire parser. */
-void
+static void
dump_parser (void)
{
int f;
if (def && (def->type == SBC_VARLIST))
{
if (def->type == SBC_VARLIST)
- dump (1, "if (token == T_ID && is_varname (tokid) && "
- "lex_look_ahead () != '=')");
+ dump (1, "if (token == T_ID "
+ "&& dict_lookup_var (default_dict, tokid) != NULL "
+ "&& lex_look_ahead () != '=')");
else
{
- dump (0, "if ((token == T_ID && is_varname (tokid) && "
- "lex_look_ahead () != '=')");
+ dump (0, "if ((token == T_ID "
+ "&& dict_lookup_var (default_dict, tokid) "
+ "&& lex_look_ahead () != '=')");
dump (1, " || token == T_ALL)");
}
dump (1, "{");
dump (0, "p->sbc_%s++;", st_lower (def->name));
- dump (1, "if (!parse_variables (NULL, &p->%sv_%s, &p->%sn_%s, "
+ dump (1, "if (!parse_variables (default_dict, &p->%sv_%s, &p->%sn_%s, "
"PV_APPEND))",
st_lower (def->prefix), st_lower (def->name),
st_lower (def->prefix), st_lower (def->name));
}
/* Write the output file header. */
-void
+static void
dump_header (void)
{
time_t curtime;
}
/* Write out commands to free variable state. */
-void
+static void
dump_free (void)
{
subcommand *sbc;
/* Returns the name of a directive found on the current input line, if
any, or a null pointer if none found. */
-const char *
+static const char *
recognize_directive (void)
{
static char directive[16];
02111-1307, USA. */
#include <config.h>
+#include "random.h"
#include <assert.h>
#include <inttypes.h>
#include <limits.h>
#include <time.h>
#include "alloc.h"
#include "magic.h"
-#include "random.h"
#include "settings.h"
/* Random number generator. */
struct rng *rng;
static time_t t;
- rng = xmalloc (sizeof *rng);
- if (t == 0)
- time (&t);
- else
- t++;
- rng_seed (rng, &t, sizeof t);
- rng->next_normal = NOT_DOUBLE;
- return rng;
- }
+ rng = xmalloc (sizeof *rng);
+ if (t == 0)
+ time (&t);
+ else
+ t++;
+ rng_seed (rng, &t, sizeof t);
+ rng->next_normal = NOT_DOUBLE;
+ return rng;
+}
/* Destroys RNG. */
void
}
/* Swap bytes. */
-static inline void
+static void
swap_byte (uint8_t *a, uint8_t *b)
{
uint8_t t = *a;
rng_seed (struct rng *rng, const void *key_, size_t size)
{
const uint8_t *key = key_;
- int key_idx;
+ size_t key_idx;
uint8_t *s;
int i, j;
rng->i = rng->j = 0;
for (i = 0; i < 256; i++)
s[i] = i;
- for (key_idx = 0, i = 0; i < 256; i++)
+ for (key_idx = 0, i = j = 0; i < 256; i++)
{
j = (j + s[i] + key[key_idx]) & 255;
swap_byte (s + i, s + j);
#if !random_h
#define random_h 1
+#include <stddef.h>
+
struct rng *rng_create (void);
void rng_destroy (struct rng *);
void rng_seed (struct rng *, const void *, size_t);
rcd->sysmis.f = 0;
/* Parse variable names. */
- if (!parse_variables (NULL, &v, &nv, PV_SAME_TYPE))
+ if (!parse_variables (default_dict, &v, &nv, PV_SAME_TYPE))
goto lossage;
/* Ensure all variables are same type; find length of longest
if ((rcd->flags & RCD_DEST_MASK) == RCD_DEST_STRING)
for (i = 0, iter = rcd; i < nv; i++, iter = iter->next)
{
- struct variable *v = find_variable (names[i]);
+ struct variable *v = dict_lookup_var (default_dict, names[i]);
if (!v)
{
else
for (i = 0, iter = rcd; i < nv; i++, iter = iter->next)
{
- struct variable *v = find_variable (names[i]);
+ struct variable *v = dict_lookup_var (default_dict, names[i]);
if (v)
{
for (rcd = head; rcd; rcd = rcd->next)
if (rcd->dest_name[0])
{
- rcd->dest = create_variable (&default_dict, rcd->dest_name,
- NUMERIC, 0);
+ rcd->dest = dict_create_var (default_dict, rcd->dest_name, 0);
if (!rcd->dest)
{
/* This can occur if a destname is duplicated. We could
give an error at parse time but I don't care enough. */
- rcd->dest = find_variable (rcd->dest_name);
+ rcd->dest = dict_lookup_var (default_dict, rcd->dest_name);
assert (rcd->dest != NULL);
}
else
success, NOT_LONG on failure. On success stores a pointer to the
first character after the number into *ENDPTR. From the GNU C
library. */
-long int
+static long int
string_to_long (char *nptr, int width, char **endptr)
{
int negative;
#include "str.h"
#include "var.h"
-/* FIXME: should change weighting variable, etc. */
-static int compare_name (const void *, const void *);
-
/* The code for this function is very similar to the code for the
RENAME subcommand of MODIFY VARS. */
int
cmd_rename_variables (void)
{
- char (*names)[8] = NULL;
-
- struct variable **old_names = NULL;
- char **new_names = NULL;
- int n_rename = 0;
+ struct variable **rename_vars = NULL;
+ char **rename_new_names = NULL;
+ int rename_cnt = 0;
+ char *err_name;
- struct variable *head, *tail, *iter;
+ int status = CMD_FAILURE;
int i;
do
{
- int prev_nv_1 = n_rename;
- int prev_nv_2 = n_rename;
+ int prev_nv_1 = rename_cnt;
+ int prev_nv_2 = rename_cnt;
if (!lex_match ('('))
{
msg (SE, _("`(' expected."));
goto lossage;
}
- if (!parse_variables (&default_dict, &old_names, &n_rename,
+ if (!parse_variables (default_dict, &rename_vars, &rename_cnt,
PV_APPEND | PV_NO_DUPLICATE))
goto lossage;
if (!lex_match ('='))
msg (SE, _("`=' expected between lists of new and old variable names."));
goto lossage;
}
- if (!parse_DATA_LIST_vars (&new_names, &prev_nv_1, PV_APPEND))
+ if (!parse_DATA_LIST_vars (&rename_new_names, &prev_nv_1, PV_APPEND))
goto lossage;
- if (prev_nv_1 != n_rename)
+ if (prev_nv_1 != rename_cnt)
{
msg (SE, _("Differing number of variables in old name list "
"(%d) and in new name list (%d)."),
- n_rename - prev_nv_2, prev_nv_1 - prev_nv_2);
+ rename_cnt - prev_nv_2, prev_nv_1 - prev_nv_2);
for (i = 0; i < prev_nv_1; i++)
- free (new_names[i]);
- free (new_names);
- new_names = NULL;
+ free (rename_new_names[i]);
+ free (rename_new_names);
+ rename_new_names = NULL;
goto lossage;
}
if (!lex_match (')'))
}
while (token != '.');
- /* Form a linked list of the variables to be renamed; also, set
- their p.mfv.new_name members. */
- head = NULL;
- for (i = 0; i < n_rename; i++)
+ if (!dict_rename_vars (default_dict,
+ rename_vars, rename_new_names, rename_cnt,
+ &err_name))
{
- strcpy (old_names[i]->p.mfv.new_name, new_names[i]);
- free (new_names[i]);
- if (head != NULL)
- tail = tail->p.mfv.next = old_names[i];
- else
- head = tail = old_names[i];
+ msg (SE, _("Renaming would duplicate variable name %s."), err_name);
+ goto lossage;
}
- tail->p.mfv.next = NULL;
- free (new_names);
- free (old_names);
- new_names = NULL;
- old_names = NULL;
- /* Construct a vector of all variables' new names. */
- names = xmalloc (8 * default_dict.nvar);
- for (i = 0; i < default_dict.nvar; i++)
- strncpy (names[i], default_dict.var[i]->name, 8);
- for (iter = head; iter; iter = iter->p.mfv.next)
- strncpy (names[iter->index], iter->p.mfv.new_name, 8);
+ status = CMD_SUCCESS;
- /* Sort the vector, then check for duplicates. */
- qsort (names, default_dict.nvar, 8, compare_name);
- for (i = 1; i < default_dict.nvar; i++)
- if (memcmp (names[i], names[i - 1], 8) == 0)
- {
- char name[9];
- strncpy (name, names[i], 8);
- name[8] = 0;
- msg (SE, _("Duplicate variable name `%s' after renaming."), name);
- goto lossage;
- }
- free (names);
-
- /* Finally, do the renaming. */
- for (iter = head; iter; iter = iter->p.mfv.next)
- hsh_force_delete (default_dict.name_tab, iter);
- for (iter = head; iter; iter = iter->p.mfv.next)
+ lossage:
+ free (rename_vars);
+ if (rename_new_names != NULL)
{
- strcpy (iter->name, iter->p.mfv.new_name);
- hsh_force_insert (default_dict.name_tab, iter);
+ for (i = 0; i < rename_cnt; i++)
+ free (rename_new_names[i]);
+ free (rename_new_names);
}
-
- return CMD_SUCCESS;
-
-lossage:
- if (new_names)
- for (i = 0; i < n_rename; i++)
- free (new_names[i]);
- free (new_names);
- free (old_names);
- free (names);
- return CMD_FAILURE;
-}
-
-static int
-compare_name (const void *a, const void *b)
-{
- return memcmp (a, b, 8);
+ return status;
}
02111-1307, USA. */
#include <config.h>
+#include "repeat.h"
#include <assert.h>
#include <ctype.h>
#include <math.h>
{
/* Note that if the variable already exists there is no
harm done. */
- struct variable *v = create_variable (&default_dict,
+ struct variable *v = dict_create_var (default_dict,
iter->replacement[i],
- NUMERIC, 0);
+ 0);
/* If we created the variable then we need to initialize
its observations to SYSMIS. */
\f
/* Finds a DO REPEAT macro with name MACRO_NAME and returns the
appropriate subsitution if found, or NULL if not. */
-char *
+static char *
find_DO_REPEAT_substitution (char *macro_name)
{
struct getl_script *s;
--- /dev/null
+/* PSPP - computes sample statistics.
+ Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Written by Ben Pfaff <blp@gnu.org>.
+
+ 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 the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#if !INCLUDED_REPEAT_H
+#define INCLUDED_REPEAT_H 1
+
+void perform_DO_REPEAT_substitutions (void);
+
+#endif /* repeat.h */
lex_match_id ("FILTER");
if (lex_match_id ("OFF"))
- default_dict.filter_var[0] = 0;
+ dict_set_filter (default_dict, NULL);
else
{
struct variable *v;
msg (SE, _("The filter variable may not be scratch."));
return CMD_FAILURE;
}
-
- strcpy (default_dict.filter_var, v->name);
+
+ dict_set_filter (default_dict, v);
FILTER_before_TEMPORARY = !temporary;
}
*/
#include <config.h>
+#include "settings.h"
#include <assert.h>
#include <stdio.h>
#include <errno.h>
#include "output.h"
#include "var.h"
#include "format.h"
-#include "settings.h"
double set_blanks;
int set_compression;
return 0;
}
-\f
-/* GSET. */
-
-int
-cmd_gset (void)
-{
- /* FIXME */
- return CMD_FAILURE;
-}
-
/*
Local Variables:
mode: c
#endif
#endif
+#include "sfm.h"
+#include "sfmP.h"
#include <assert.h>
#include <stdlib.h>
#include <ctype.h>
#include "hash.h"
#include "magic.h"
#include "misc.h"
-#include "sfm.h"
-#include "sfmP.h"
#include "value-labels.h"
#include "str.h"
#include "var.h"
lose ((ME, _("%s: Weighting variable may not be a string variable."),
h->fn));
- strcpy (ext->dict->weight_var, wv->name);
+ dict_set_weight (ext->dict, wv);
}
else
- ext->dict->weight_var[0] = 0;
+ dict_set_weight (ext->dict, NULL);
/* Read records of types 3, 4, 6, and 7. */
for (;;)
free (var_by_index);
fn_close (h->fn, ext->file);
if (ext && ext->dict)
- free_dictionary (ext->dict);
+ dict_destroy (ext->dict);
free (ext);
h->class = NULL;
h->ext = NULL;
int i;
/* Create the dictionary. */
- dict = ext->dict = xmalloc (sizeof *dict);
- dict->var = NULL;
- dict->name_tab = NULL;
- dict->nvar = 0;
- dict->N = 0;
- dict->nval = -1; /* Unknown. */
- dict->n_splits = 0;
- dict->splits = NULL;
- dict->weight_var[0] = 0;
- dict->weight_index = -1;
- dict->filter_var[0] = 0;
- dict->label = NULL;
- dict->n_documents = 0;
- dict->documents = NULL;
+ dict = ext->dict = dict_create ();
/* Read header, check magic. */
assertive_bufread (h, &hdr, sizeof hdr, 0);
{
int i;
- dict->label = NULL;
for (i = sizeof hdr.file_label - 1; i >= 0; i--)
if (!isspace ((unsigned char) hdr.file_label[i])
&& hdr.file_label[i] != 0)
{
- dict->label = xmalloc (i + 2);
- memcpy (dict->label, hdr.file_label, i + 1);
- dict->label[i + 1] = 0;
+ char *label = xmalloc (i + 2);
+ memcpy (label, hdr.file_label, i + 1);
+ label[i + 1] = 0;
+ dict_set_label (dict, label);
+ free (label);
break;
}
}
}
/* Reads most of the dictionary from file H; also fills in the
- associated VAR_BY_INDEX array.
-
- Note: the dictionary returned by this function has an invalid NVAL
- element, also the VAR[] array does not have the FV and LV elements
- set, however the NV elements *are* set. This is because the caller
- will probably modify the dictionary before reading it in from the
- file. Also, the get.* elements are set to appropriate values to
- allow the file to be read. */
+ associated VAR_BY_INDEX array. The get.* elements in the
+ created dictionary are set to appropriate values to allow the
+ file to be read. */
static int
read_variables (struct file_handle * h, struct variable *** var_by_index)
{
int next_value = 0; /* Index to next `value' structure. */
/* Allocate variables. */
- dict->var = xmalloc (sizeof *dict->var * ext->case_size);
*var_by_index = xmalloc (sizeof **var_by_index * ext->case_size);
/* Read in the entry for each variable and use the info to
for (i = 0; i < ext->case_size; i++)
{
struct variable *vv;
+ char name[9];
int j;
assertive_bufread (h, &sv, sizeof sv, 0);
lose ((ME, _("%s: position %d: Missing value indicator field is not "
"-3, -2, 0, 1, 2, or 3."), h->fn, i));
- /* Construct internal variable structure, initialize critical bits. */
- vv = (*var_by_index)[i] = dict->var[dict->nvar++] = xmalloc (sizeof *vv);
- vv->index = dict->nvar - 1;
- vv->foo = -1;
- vv->label = NULL;
-
/* Copy first character of variable name. */
if (!isalpha ((unsigned char) sv.name[0])
&& sv.name[0] != '@' && sv.name[0] != '#')
msg (MW, _("%s: position %d: Variable name begins with octothorpe "
"(`#'). Scratch variables should not appear in system "
"files."), h->fn, i);
- vv->name[0] = toupper ((unsigned char) (sv.name[0]));
+ name[0] = toupper ((unsigned char) (sv.name[0]));
/* Copy remaining characters of variable name. */
for (j = 1; j < 8; j++)
{
msg (MW, _("%s: position %d: Variable name character %d is "
"lowercase letter %c."), h->fn, i, j + 1, sv.name[j]);
- vv->name[j] = toupper ((unsigned char) (c));
+ name[j] = toupper ((unsigned char) (c));
}
else if (isalnum (c) || c == '.' || c == '@'
|| c == '#' || c == '$' || c == '_')
- vv->name[j] = c;
+ name[j] = c;
else
lose ((ME, _("%s: position %d: character `\\%03o' (%c) is not valid in a "
"variable name."), h->fn, i, c, c));
}
- vv->name[j] = 0;
-
- /* Set type, width, and `left' fields and allocate `value'
- indices. */
- if (sv.type == 0)
- {
- vv->type = NUMERIC;
- vv->width = 0;
- vv->get.nv = 1;
- vv->get.fv = next_value++;
- vv->nv = 1;
- }
+ name[j] = 0;
+
+ /* Create variable. */
+ vv = (*var_by_index)[i] = dict_create_var (dict, name, sv.type);
+ if (vv == NULL)
+ lose ((ME, _("%s: Duplicate variable name `%s' within system file."),
+ h->fn, name));
+
+ /* Case reading data. */
+ vv->get.fv = next_value;
+ if (sv.type == 0)
+ vv->get.nv = 1;
else
- {
- vv->type = ALPHA;
- vv->width = sv.type;
- vv->nv = DIV_RND_UP (vv->width, MAX_SHORT_STRING);
- vv->get.nv = DIV_RND_UP (vv->width, sizeof (flt64));
- vv->get.fv = next_value;
- next_value += vv->get.nv;
- long_string_count = vv->get.nv - 1;
- }
- vv->left = (vv->name[0] == '#');
- vv->val_labs = val_labs_create (vv->width);
+ vv->get.nv = DIV_RND_UP (sv.type, sizeof (flt64));
+ long_string_count = vv->get.nv - 1;
+ next_value += vv->get.nv;
/* Get variable label, if any. */
if (sv.has_var_label == 1)
if (next_value != ext->case_size)
lose ((ME, _("%s: System file header indicates %d variable positions but "
"%d were read from file."), h->fn, ext->case_size, next_value));
- dict->var = xrealloc (dict->var, sizeof *dict->var * dict->nvar);
-
- /* Construct hash table of dictionary in order to speed up
- later processing and to check for duplicate varnames. */
- dict->name_tab = hsh_create (8, compare_variables, hash_variable,
- NULL, NULL);
- for (i = 0; i < dict->nvar; i++)
- if (NULL != hsh_insert (dict->name_tab, dict->var[i]))
- lose ((ME, _("%s: Duplicate variable name `%s' within system file."),
- h->fn, dict->var[i]->name));
return 1;
lossage:
- for (i = 0; i < dict->nvar; i++)
- {
- free (dict->var[i]->label);
- free (dict->var[i]);
- }
- free (dict->var);
- if (dict->name_tab)
- hsh_destroy (dict->name_tab);
- free (dict);
+ dict_destroy (dict);
ext->dict = NULL;
return 0;
assertive_bufread (h, &n_vars, sizeof n_vars, 0);
if (ext->reverse_endian)
bswap_int32 (&n_vars);
- if (n_vars < 1 || n_vars > ext->dict->nvar)
+ if (n_vars < 1 || n_vars > dict_get_var_cnt (ext->dict))
lose ((ME, _("%s: Number of variables associated with a value label (%d) "
"is not between 1 and the number of variables (%d)."),
- h->fn, n_vars, ext->dict->nvar));
+ h->fn, n_vars, dict_get_var_cnt (ext->dict)));
/* Read the list of variables. */
var = xmalloc (n_vars * sizeof *var);
for (i = 0; i < n_labels; i++)
free (labels[i].label);
+ free (labels);
free (var);
return 1;
struct sfm_fhuser_ext *ext = h->ext;
struct dictionary *dict = ext->dict;
int32 n_lines;
+ char *documents;
- if (dict->documents != NULL)
+ if (dict_get_documents (dict) != NULL)
lose ((ME, _("%s: System file contains multiple type 6 (document) records."),
h->fn));
assertive_bufread (h, &n_lines, sizeof n_lines, 0);
- dict->n_documents = n_lines;
- if (dict->n_documents <= 0)
+ if (n_lines <= 0)
lose ((ME, _("%s: Number of document lines (%ld) must be greater than 0."),
- h->fn, (long) dict->n_documents));
+ h->fn, (long) n_lines));
- dict->documents = bufread (h, NULL, 80 * n_lines, 0);
- if (dict->documents == NULL)
+ documents = bufread (h, NULL, 80 * n_lines, n_lines * 80 + 1);
+ /* FIXME? Run through asciify. */
+ if (documents == NULL)
return 0;
+ documents[80 * n_lines] = '\0';
+ dict_set_documents (dict, documents);
+ free (documents);
return 1;
lossage:
int n, j;
debug_printf ((" var %s", v->name));
- /*debug_printf (("(indices:%d,%d)", v->index, v->foo));*/
debug_printf (("(type:%s,%d)", (v->type == NUMERIC ? _("num")
: (v->type == ALPHA ? _("str") : "!!!")),
v->width));
debug_printf (("(fv:%d,%d)", v->fv, v->nv));
- /*debug_printf (("(get.fv:%d,%d)", v->get.fv, v->get.nv));*/
debug_printf (("(left:%s)(miss:", v->left ? _("left") : _("right")));
switch (v->miss_type)
int i;
- /* Make sure the caller remembered to finish polishing the
- dictionary returned by sfm_read_dictionary(). */
- assert (dict->nval > 0);
-
/* The first concern is to obtain a full case relative to the data
file. (Cases in the data file have no particular relationship to
cases in the active file.) */
/* Translate a case in data file format to a case in active file
format. */
- for (i = 0; i < dict->nvar; i++)
+ for (i = 0; i < dict_get_var_cnt (dict); i++)
{
- struct variable *v = dict->var[i];
+ struct variable *v = dict_get_var (dict, i);
if (v->get.fv == -1)
continue;
#endif
#endif
+#include "sfm.h"
+#include "sfmP.h"
#include <assert.h>
#include <stdlib.h>
#include <ctype.h>
#include "hash.h"
#include "magic.h"
#include "misc.h"
-#include "sfm.h"
-#include "sfmP.h"
#include "str.h"
#include "value-labels.h"
#include "var.h"
goto lossage;
/* Write basic variable info. */
- for (i = 0; i < d->nvar; i++)
- write_variable (inf, d->var[i]);
+ for (i = 0; i < dict_get_var_cnt (d); i++)
+ write_variable (inf, dict_get_var (d, i));
/* Write out value labels. */
- for (index = i = 0; i < d->nvar; i++)
+ for (index = i = 0; i < dict_get_var_cnt (d); i++)
{
- struct variable *v = d->var[i];
+ struct variable *v = dict_get_var (d, i);
if (!write_value_labels (inf, v, index))
goto lossage;
: DIV_RND_UP (v->width, sizeof (flt64)));
}
- if (d->documents != NULL && !write_documents (inf))
+ if (dict_get_documents (d) != NULL && !write_documents (inf))
goto lossage;
if (!write_rec_7_34 (inf))
goto lossage;
hdr.layout_code = 2;
hdr.case_size = 0;
- for (i = 0; i < d->nvar; i++)
+ for (i = 0; i < dict_get_var_cnt (d); i++)
{
- struct variable *v = d->var[i];
+ struct variable *v = dict_get_var (d, i);
hdr.case_size += (v->type == NUMERIC ? 1
: DIV_RND_UP (v->width, sizeof (flt64)));
}
inf->case_size = hdr.case_size;
p = ext->elem_type = xmalloc (inf->case_size);
- for (i = 0; i < d->nvar; i++)
+ for (i = 0; i < dict_get_var_cnt (d); i++)
{
- struct variable *v = d->var[i];
+ struct variable *v = dict_get_var (d, i);
int count = (v->type == NUMERIC ? 1
: DIV_RND_UP (v->width, sizeof (flt64)));
while (count--)
hdr.compressed = inf->compress;
- update_weighting (d);
- if (d->weight_index != -1)
+ if (dict_get_weight (d) != NULL)
{
+ struct variable *weight_var;
int recalc_weight_index = 1;
+ int i;
- for (i = 0; i < d->weight_index; i++)
- {
- struct variable *v = d->var[i];
+ weight_var = dict_get_weight (d);
+ for (i = 0; ; i++)
+ {
+ struct variable *v = dict_get_var (d, i);
+ if (v == weight_var)
+ break;
recalc_weight_index += (v->type == NUMERIC ? 1
: DIV_RND_UP (v->width, sizeof (flt64)));
}
sprintf (buf, "%02d:%02d:%02d", hour - 1, min - 1, sec - 1);
memcpy (hdr.creation_time, buf, sizeof hdr.creation_time);
}
+
+ {
+ const char *label = dict_get_label (d);
+ if (label == NULL)
+ label = "";
- st_bare_pad_copy (hdr.file_label, d->label ? d->label : "",
- sizeof hdr.file_label);
+ st_bare_pad_copy (hdr.file_label, label, sizeof hdr.file_label);
+ }
+
memset (hdr.padding, 0, sizeof hdr.padding);
if (!bufwrite (inf->h, &hdr, sizeof hdr))
}
rec_6;
+ const char *documents;
+ size_t n_lines;
+
+ documents = dict_get_documents (d);
+ n_lines = strlen (documents) / 80;
+
rec_6.rec_type = 6;
- rec_6.n_lines = d->n_documents;
+ rec_6.n_lines = n_lines;
if (!bufwrite (inf->h, &rec_6, sizeof rec_6))
return 0;
- if (!bufwrite (inf->h, d->documents, 80 * d->n_documents))
+ if (!bufwrite (inf->h, documents, 80 * n_lines))
return 0;
return 1;
02111-1307, USA. */
#include <config.h>
+#include "som.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "output.h"
-#include "som.h"
#include "debug-print.h"
/* Table. */
02111-1307, USA. */
#include <config.h>
+#include "sort.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "heap.h"
#include "lexer.h"
#include "misc.h"
-#include "sort.h"
#include "str.h"
#include "var.h"
#include "vfm.h"
int prev_nv_sort = nv_sort;
int order = SRT_ASCEND;
- if (!parse_variables (&default_dict, &v_sort, &nv_sort,
+ if (!parse_variables (default_dict, &v_sort, &nv_sort,
PV_NO_DUPLICATE | PV_APPEND | PV_NO_SCRATCH))
return 0;
if (lex_match ('('))
{
/* This is the size of one case. */
const int case_size = (sizeof (struct repl_sel_tree)
- + sizeof (union value) * (default_dict.nval - 1)
+ + (sizeof (union value)
+ * (dict_get_value_cnt (default_dict) - 1))
+ sizeof (struct repl_sel_tree *));
x = NULL;
for (i = 0; i < x_max; i++)
{
x[i] = malloc (sizeof (struct repl_sel_tree)
- + sizeof (union value) * (default_dict.nval - 1));
+ + (sizeof (union value)
+ * (dict_get_value_cnt (default_dict) - 1)));
if (x[i] == NULL)
break;
}
J->rn = 0;
J->fe = x[(x_max + j) / 2];
J->fi = x[j / 2];
- memset (J->record, 0, default_dict.nval * sizeof (union value));
+ memset (J->record, 0,
+ dict_get_value_cnt (default_dict) * sizeof (union value));
}
}
order = MAX_MERGE_ORDER;
if (x_max / order < MIN_BUFFER_SIZE_RECS)
order = x_max / MIN_BUFFER_SIZE_RECS;
- else if (x_max / order * sizeof (union value) * default_dict.nval
+ else if (x_max / order * sizeof (union value) * dict_get_value_cnt (default_dict)
< MIN_BUFFER_SIZE_BYTES)
order = x_max / (MIN_BUFFER_SIZE_BYTES
- / (sizeof (union value) * (default_dict.nval - 1)));
+ / (sizeof (union value)
+ * (dict_get_value_cnt (default_dict) - 1)));
/* Make sure the order of merge is bounded. */
if (order < 2)
buffered[i] = min (records_per_buffer, run_length[i]);
for (j = 0; j < buffered[i]; j++)
if ((int) fread (x[j + ofs]->record, sizeof (union value),
- default_dict.nval, handle[i])
- != default_dict.nval)
+ dict_get_value_cnt (default_dict), handle[i])
+ != dict_get_value_cnt (default_dict))
{
sprintf (tmp_extname, "%08x", run_index[i]);
if (ferror (handle[i]))
min = i;
if ((int) fwrite (x[buffer_ptr[min]]->record, sizeof (union value),
- default_dict.nval, handle[N_INPUT_BUFFERS])
- != default_dict.nval)
+ dict_get_value_cnt (default_dict),
+ handle[N_INPUT_BUFFERS])
+ != dict_get_value_cnt (default_dict))
{
sprintf (tmp_extname, "%08x", run_index[i]);
msg (SE, _("%s: Error writing temporary file in "
buffered[min] = min (records_per_buffer, run_length[min]);
for (j = 0; j < buffered[min]; j++)
if ((int) fread (x[j + ofs]->record, sizeof (union value),
- default_dict.nval, handle[min])
- != default_dict.nval)
+ dict_get_value_cnt (default_dict),
+ handle[min])
+ != dict_get_value_cnt (default_dict))
{
sprintf (tmp_extname, "%08x", run_index[min]);
if (ferror (handle[min]))
/* Reads all the records from the source stream and passes them
to write_case(). */
-void
+static void
sort_stream_read (void)
{
read_sort_output (write_case);
}
/* Switches mode from sink to source. */
-void
+static void
sort_stream_mode (void)
{
/* If this is not done, then we get the following source/sink pairs:
lex_match_id ("FILE");
if (lex_match_id ("OFF"))
- {
- default_dict.n_splits = 0;
- free (default_dict.splits);
- default_dict.splits = NULL;
- }
+ dict_set_split_vars (default_dict, NULL, 0);
else
{
struct variable **v;
int n;
lex_match (T_BY);
- if (!parse_variables (NULL, &v, &n, PV_NO_DUPLICATE))
+ if (!parse_variables (default_dict, &v, &n, PV_NO_DUPLICATE))
return CMD_FAILURE;
- default_dict.n_splits = n;
- default_dict.splits = v = xrealloc (v, sizeof *v * (n + 1));
- v[n] = NULL;
+ dict_set_split_vars (default_dict, v, n);
+ free (v);
}
return lex_end_of_command ();
02111-1307, USA. */
#include <config.h>
-#include <math.h>
#include "stats.h"
+#include <math.h>
/* Returns the fourth power of its argument. */
double
-hypercube (double x)
+pow4 (double x)
{
x *= x;
return x * x;
(((n + 1) * (n * d[3]
- 4.0 * d[0] * d[2]
+ 6.0 * sqr (d[0]) * d[1] / n
- - 3.0 * hypercube (d[0]) / sqr (n)))
+ - 3.0 * pow4 (d[0]) / sqr (n)))
/ ((n - 1.0) * (n - 2.0) * (n - 3.0) * sqr (variance))
- (3.0 * sqr (n - 1.0))
/ ((n - 2.0) * (n - 3.)));
#endif /* !PI && !M_PI */
#endif /* !PI */
+extern double pow4 (double);
+extern double cube (double);
+extern double sqr (double);
+
/* Returns the fourth power of its argument. */
extern inline double
-hypercube (double x)
+pow4 (double x)
{
x *= x;
return x * x;
02111-1307, USA. */
#include <config.h>
+#include "str.h"
#include <assert.h>
#include <ctype.h>
#include <limits.h>
#include "alloc.h"
#include "error.h"
#include "pool.h"
-#include "str.h"
\f
/* sprintf() wrapper functions for convenience. */
#include "tab.h"
#include "value-labels.h"
#include "var.h"
-#include "vector.h"
/* Constants for DISPLAY utility. */
enum
tab_text (t, 0, 0, TAB_LEFT, _("File:"));
tab_text (t, 1, 0, TAB_LEFT, fh_handle_filename (h));
tab_text (t, 0, 1, TAB_LEFT, _("Label:"));
- tab_text (t, 1, 1, TAB_LEFT,
- d->label ? d->label : _("No label."));
+ {
+ const char *label = dict_get_label (d);
+ if (label == NULL)
+ label = _("No label.");
+ tab_text (t, 1, 1, TAB_LEFT, label);
+ }
tab_text (t, 0, 2, TAB_LEFT, _("Created:"));
tab_text (t, 1, 2, TAB_LEFT | TAT_PRINTF, "%s %s by %s",
inf.creation_date, inf.creation_time, inf.product);
tab_text (t, 1, 3, TAB_LEFT, inf.bigendian ? _("Big.") : _("Little."));
tab_text (t, 0, 4, TAB_LEFT, _("Variables:"));
tab_text (t, 1, 4, TAB_LEFT | TAT_PRINTF, "%d",
- d->nvar);
+ dict_get_var_cnt (d));
tab_text (t, 0, 5, TAB_LEFT, _("Cases:"));
tab_text (t, 1, 5, TAB_LEFT | TAT_PRINTF,
inf.ncases == -1 ? _("Unknown") : "%d", inf.ncases);
tab_text (t, 0, 6, TAB_LEFT, _("Type:"));
tab_text (t, 1, 6, TAB_LEFT, _("System File."));
tab_text (t, 0, 7, TAB_LEFT, _("Weight:"));
- tab_text (t, 1, 7, TAB_LEFT,
- d->weight_var[0] ? d->weight_var : _("Not weighted."));
+ {
+ struct variable *weight_var = dict_get_weight (d);
+ tab_text (t, 1, 7, TAB_LEFT,
+ weight_var != NULL ? weight_var->name : _("Not weighted."));
+ }
tab_text (t, 0, 8, TAB_LEFT, _("Mode:"));
tab_text (t, 1, 8, TAB_LEFT | TAT_PRINTF,
_("Compression %s."), inf.compressed ? _("on") : _("off"));
tab_dim (t, tab_natural_dimensions);
tab_submit (t);
- nr = 1 + 2 * d->nvar;
+ nr = 1 + 2 * dict_get_var_cnt (d);
t = tab_create (4, nr, 1);
tab_dim (t, sysfile_info_dim);
tab_headers (t, 0, 0, 1, 0);
tab_joint_text (t, 1, 0, 2, 0, TAB_LEFT | TAT_TITLE, _("Description"));
tab_text (t, 3, 0, TAB_LEFT | TAT_TITLE, _("Position"));
tab_hline (t, TAL_2, 0, 3, 1);
- for (r = 1, i = 0; i < d->nvar; i++)
+ for (r = 1, i = 0; i < dict_get_var_cnt (d); i++)
{
- int nvl = val_labs_count (d->var[i]->val_labs);
+ struct variable *v = dict_get_var (d, i);
+ int nvl = val_labs_count (v->val_labs);
if (r + 10 + nvl > nr)
{
- nr = max (nr * d->nvar / (i + 1), nr);
+ nr = max (nr * dict_get_var_cnt (d) / (i + 1), nr);
nr += 10 + nvl;
tab_realloc (t, 4, nr);
}
- r = describe_variable (d->var[i], t, r, AS_DICTIONARY);
+ r = describe_variable (v, t, r, AS_DICTIONARY);
}
tab_box (t, TAL_1, TAL_1, -1, -1, 0, 0, 3, r);
tab_vline (t, TAL_1, 0, 0, r);
tab_flags (t, SOMF_NO_TITLE);
tab_submit (t);
- free_dictionary (d);
+ dict_destroy (d);
return lex_end_of_command ();
}
som_blank_line ();
if (!lex_force_match_id ("LABEL"))
return CMD_FAILURE;
- if (default_dict.label == NULL)
+ if (dict_get_label (default_dict) == NULL)
tab_output_text (TAB_LEFT,
_("The active file does not have a file label."));
else
{
tab_output_text (TAB_LEFT | TAT_TITLE, _("File label:"));
- tab_output_text (TAB_LEFT | TAT_FIX, default_dict.label);
+ tab_output_text (TAB_LEFT | TAT_FIX, dict_get_label (default_dict));
}
}
else
if (token != '.')
{
- if (!parse_variables (NULL, &vl, &n, PV_NONE))
+ if (!parse_variables (default_dict, &vl, &n, PV_NONE))
{
free (vl);
return CMD_FAILURE;
as = AS_DICTIONARY;
}
else
- fill_all_vars (&vl, &n, FV_NONE);
+ dict_get_vars (default_dict, &vl, &n, 0);
if (as == AS_SCRATCH)
{
static void
display_documents (void)
{
+ const char *documents = dict_get_documents (default_dict);
+
som_blank_line ();
- if (default_dict.n_documents == 0)
+ if (documents == NULL)
tab_output_text (TAB_LEFT, _("The active file dictionary does not "
- "contain any documents."));
+ "contain any documents."));
else
{
+ size_t n_lines = strlen (documents) / 80;
char buf[81];
- int i;
+ size_t i;
tab_output_text (TAB_LEFT | TAT_TITLE,
_("Documents in the active file:"));
som_blank_line ();
buf[80] = 0;
- for (i = 0; i < default_dict.n_documents; i++)
+ for (i = 0; i < n_lines; i++)
{
int len = 79;
- memcpy (buf, &default_dict.documents[i * 80], 80);
+ memcpy (buf, &documents[i * 80], 80);
while ((isspace ((unsigned char) buf[len]) || buf[len] == 0)
&& len > 0)
len--;
static void
display_vectors (int sorted)
{
- struct vector **vl;
+ const struct vector **vl;
int i;
struct tab_table *t;
-
+ size_t nvec;
+
+ nvec = dict_get_vector_cnt (default_dict);
if (nvec == 0)
{
msg (SW, _("No vectors defined."));
vl = xmalloc (sizeof *vl * nvec);
for (i = 0; i < nvec; i++)
- vl[i] = &vec[i];
+ vl[i] = dict_get_vector (default_dict, i);
if (sorted)
qsort (vl, nvec, sizeof *vl, compare_vectors_by_name);
double X = c->data[v->fv].f;
/* Get the weight for this case. */
- if (default_dict.weight_index == -1)
- w = 1.0;
- else
+ w = dict_get_case_weight (default_dict, c);
+ if (w <= 0.0 || w == SYSMIS)
{
- w = c->data[default_dict.weight_index].f;
- if (w <= 0.0 || w == SYSMIS)
- {
- w = 0.0;
- bad_weight = 1;
- printf ("Bad weight\n");
- }
+ w = 0.0;
+ bad_weight = 1;
+ printf ("Bad weight\n");
}
if (X == SYSMIS || X == 0.0) /* FIXME: should be USER_MISSING? */
int /* this pass generates the z-zcores */
z_calc (struct ccase * c)
{
- int bad_weight;
double group, z, w;
struct variable *v = cmd.v_variables[cur_var];
double X = c->data[v->fv].f;
z = 0.0;
/* Get the weight for this case. */
- if (default_dict.weight_index == -1)
- w = 1.0;
- else
- {
- w = c->data[default_dict.weight_index].f;
- if (w <= 0.0 || w == SYSMIS)
- {
- w = 0.0;
- bad_weight = 1;
- }
- }
+ w = dict_get_case_weight (default_dict, c);
if (X == SYSMIS || X == 0.0) /* FIXME: how to specify user missing? */
{
int n_predicted;
#endif
- if ((token != T_ID || !is_varname (tokid)) && token != T_ALL)
+ if ((token != T_ID || dict_lookup_var (default_dict, tokid) == NULL)
+ && token != T_ALL)
return 2;
- if (!parse_variables (&default_dict, &vars, &n_vars,
+ if (!parse_variables (default_dict, &vars, &n_vars,
PV_DUPLICATE | PV_NUMERIC | PV_NO_SCRATCH))
return 0;
{
n_before_WITH = n_vars;
- if (!parse_variables (&default_dict, &vars, &n_vars,
+ if (!parse_variables (default_dict, &vars, &n_vars,
PV_DUPLICATE | PV_APPEND
| PV_NUMERIC | PV_NO_SCRATCH))
{
#endif
#endif
+#include "tab.h"
#include <ctype.h>
#include <assert.h>
#include <stdarg.h>
#include "output.h"
#include "pool.h"
#include "som.h"
-#include "tab.h"
#include "var.h"
#include "debug-print.h"
\f
-extern struct som_table_class tab_table_class;
+struct som_table_class tab_table_class;
#if DEBUGGING
#define DEFFIRST(NAME, LABEL) LABEL,
return CMD_FAILURE;
}
- /* Everything is temporary, even if we think it'll last forever.
- Especially then. */
+ /* Make a copy of the current dictionary. */
temporary = 1;
- temp_dict = save_dictionary ();
+ temp_dict = dict_clone (default_dict);
if (f_trns == n_trns)
temp_trns = -1;
else
return lex_end_of_command ();
}
-/* Copies a variable structure. */
-void
-copy_variable (struct variable *dest, const struct variable *src)
-{
- int i, n;
-
- assert (dest != src);
- dest->type = src->type;
- dest->left = src->left;
- dest->width = src->width;
- dest->fv = src->fv;
- dest->nv = src->nv;
- dest->miss_type = src->miss_type;
-
- switch (src->miss_type)
- {
- case MISSING_NONE:
- n = 0;
- break;
- case MISSING_1:
- n = 1;
- break;
- case MISSING_2:
- case MISSING_RANGE:
- n = 2;
- break;
- case MISSING_3:
- case MISSING_RANGE_1:
- n = 3;
- break;
- default:
- assert (0);
- break;
- }
-
- for (i = 0; i < n; i++)
- dest->missing[i] = src->missing[i];
- dest->print = src->print;
- dest->write = src->write;
-
- dest->val_labs = val_labs_copy (src->val_labs);
- dest->label = src->label ? xstrdup (src->label) : NULL;
-}
-
-/* Returns a newly created empty dictionary. The file label and
- documents are copied from default_dict if COPY is nonzero. */
-struct dictionary *
-new_dictionary (int copy)
-{
- struct dictionary *d = xmalloc (sizeof *d);
-
- d->var = NULL;
- d->name_tab = hsh_create (8, compare_variables, hash_variable, NULL, NULL);
- d->nvar = 0;
-
- d->N = 0;
-
- d->nval = 0;
-
- d->n_splits = 0;
- d->splits = NULL;
-
- if (default_dict.label && copy)
- d->label = xstrdup (default_dict.label);
- else
- d->label = NULL;
-
- if (default_dict.n_documents && copy)
- {
- d->n_documents = default_dict.n_documents;
- if (d->n_documents)
- {
- d->documents = malloc (default_dict.n_documents * 80);
- memcpy (d->documents, default_dict.documents,
- default_dict.n_documents * 80);
- }
- }
- else
- {
- d->n_documents = 0;
- d->documents = NULL;
- }
-
- d->weight_index = -1;
- d->weight_var[0] = 0;
-
- d->filter_var[0] = 0;
-
- return d;
-}
-
-/* Copies the current dictionary info into a newly allocated
- dictionary structure, which is returned. */
-struct dictionary *
-save_dictionary (void)
-{
- /* Dictionary being created. */
- struct dictionary *d;
-
- int i;
-
- d = xmalloc (sizeof *d);
-
- /* First the easy stuff. */
- *d = default_dict;
- d->label = default_dict.label ? xstrdup (default_dict.label) : NULL;
- if (default_dict.n_documents)
- {
- d->documents = malloc (default_dict.n_documents * 80);
- memcpy (d->documents, default_dict.documents,
- default_dict.n_documents * 80);
- }
- else d->documents = NULL;
-
- /* Then the variables. */
- d->name_tab = hsh_create (8, compare_variables, hash_variable, NULL, NULL);
- d->var = xmalloc (default_dict.nvar * sizeof *d->var);
- for (i = 0; i < default_dict.nvar; i++)
- {
- d->var[i] = xmalloc (sizeof *d->var[i]);
- copy_variable (d->var[i], default_dict.var[i]);
- strcpy (d->var[i]->name, default_dict.var[i]->name);
- d->var[i]->index = i;
- hsh_force_insert (d->name_tab, d->var[i]);
- }
-
- /* Then the SPLIT FILE variables. */
- if (default_dict.splits)
- {
- int i;
-
- d->n_splits = default_dict.n_splits;
- d->splits = xmalloc ((default_dict.n_splits + 1) * sizeof *d->splits);
- for (i = 0; i < default_dict.n_splits; i++)
- d->splits[i] = d->var[default_dict.splits[i]->index];
- d->splits[default_dict.n_splits] = NULL;
- }
- else
- {
- d->n_splits = 0;
- d->splits = NULL;
- }
-
- return d;
-}
-
-/* Copies dictionary D into the active file dictionary. Deletes
- dictionary D. */
-void
-restore_dictionary (struct dictionary * d)
-{
- int i;
-
- /* 1. Delete the current dictionary. */
- default_dict.n_splits = 0;
- free (default_dict.splits);
- default_dict.splits = NULL;
-
- hsh_destroy (default_dict.name_tab);
- default_dict.name_tab = NULL;
-
- for (i = 0; i < default_dict.nvar; i++)
- {
- clear_variable (&default_dict, default_dict.var[i]);
- free (default_dict.var[i]);
- }
-
- free (default_dict.var);
- free (default_dict.label);
- free (default_dict.documents);
-
- /* 2. Copy dictionary D into the active file dictionary. */
- default_dict = *d;
- if (default_dict.name_tab == NULL)
- {
- default_dict.name_tab = hsh_create (8, compare_variables, hash_variable,
- NULL, NULL);
-
- for (i = 0; i < default_dict.nvar; i++)
- hsh_force_insert (default_dict.name_tab, default_dict.var[i]);
- }
-
- /* 3. Destroy dictionary D. */
- free (d);
-}
-
-/* Destroys dictionary D. */
-void
-free_dictionary (struct dictionary * d)
-{
- int i;
-
- d->n_splits = 0;
- free (d->splits);
- d->splits = NULL;
-
- if (d->name_tab)
- hsh_destroy (d->name_tab);
-
- for (i = 0; i < d->nvar; i++)
- {
- struct variable *v = d->var[i];
-
- val_labs_destroy (v->val_labs);
- if (v->label)
- {
- free (v->label);
- v->label = NULL;
- }
- free (d->var[i]);
- }
- free (d->var);
-
- free (d->label);
- free (d->documents);
-
- free (d);
-}
-
/* Cancels the temporary transformation, if any. */
void
cancel_temporary (void)
{
if (temporary)
{
- if (temp_dict)
- free_dictionary (temp_dict);
+ if (temp_dict)
+ {
+ dict_destroy (temp_dict);
+ temp_dict = NULL;
+ }
temporary = 0;
temp_trns = 0;
}
while (isspace ((unsigned char) *label))
label++;
- free (default_dict.label);
- default_dict.label = xstrdup (label);
- if (strlen (default_dict.label) > 60)
- default_dict.label[60] = 0;
+ dict_set_label (default_dict, label);
token = '.';
return CMD_SUCCESS;
static void
add_document_line (const char *line, int indent)
{
- char *doc;
-
- default_dict.n_documents++;
- default_dict.documents = xrealloc (default_dict.documents,
- 80 * default_dict.n_documents);
- doc = &default_dict.documents[80 * (default_dict.n_documents - 1)];
- memset (doc, ' ', indent);
- st_bare_pad_copy (&doc[indent], line, 80 - indent);
+ const char *old_documents;
+ size_t old_len;
+ char *new_documents;
+
+ old_documents = dict_get_documents (default_dict);
+ old_len = old_documents != NULL ? strlen (old_documents) : 0;
+ new_documents = xmalloc (old_len + 81);
+
+ memcpy (new_documents, old_documents, old_len);
+ memset (new_documents + old_len, ' ', indent);
+ st_bare_pad_copy (new_documents + old_len + indent, line, 80 - indent);
+ new_documents[old_len + 80] = '\0';
+
+ dict_set_documents (default_dict, new_documents);
+
+ free (new_documents);
}
/* Performs the DOCUMENT command. */
char buf[256];
struct tm *tmp = localtime (&last_vfm_invocation);
- if (default_dict.n_documents)
+ if (dict_get_documents (default_dict) != NULL)
add_document_line ("", 0);
sprintf (buf, _("Document entered %s %02d:%02d:%02d by %s (%s):"),
lex_match_id ("DROP");
lex_match_id ("DOCUMENTS");
- free (default_dict.documents);
- default_dict.documents = NULL;
- default_dict.n_documents = 0;
+ dict_set_documents (default_dict, NULL);
return lex_end_of_command ();
}
while (token != '.')
{
- parse_variables (NULL, &v, &nv, PV_SAME_TYPE);
+ parse_variables (default_dict, &v, &nv, PV_SAME_TYPE);
if (!verify_val_labs (erase))
return CMD_PART_SUCCESS_MAYBE;
while (token != '/' && token != '.')
02111-1307, USA. */
#include <config.h>
+#include "value-labels.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "alloc.h"
#include "hash.h"
-#include "value-labels.h"
static hsh_compare_func compare_int_val_lab;
static hsh_hash_func hash_int_val_lab;
void
val_labs_destroy (struct val_labs *vls)
{
- if (vls != NULL && vls->labels != NULL)
- hsh_destroy (vls->labels);
+ if (vls != NULL)
+ {
+ if (vls->labels != NULL)
+ hsh_destroy (vls->labels);
+ free (vls);
+ }
}
/* Removes all the value labels from VLS. */
lex_match ('/');
do
{
- parse_variables (NULL, &v, &nv, PV_NONE);
+ parse_variables (default_dict, &v, &nv, PV_NONE);
if (token != T_STRING)
{
#if !var_h
#define var_h 1
+#include <stddef.h>
#include "format.h"
/* Values. */
double total_cases; /* Sum of weights of all cases. */
double valid_cases; /* Sum of weights of valid cases. */
};
-
-/* A complete set of 3 frequency tables. */
-struct freq_tab_set
- {
- struct freq_tab miss; /* Includes user-missing values. */
- struct freq_tab no_miss; /* Excludes user-missing values. */
- struct freq_tab sel; /* Identical to either miss or no_miss. */
- };
\f
/* Procedures' private per-variable data. */
struct frequencies_proc
{
- /* General mode. */
+ int used; /* 1=This variable already used. */
+
+ /* Freqency table. */
struct freq_tab tab; /* Frequencies table to use. */
/* Percentiles. */
/* GET private data. */
struct get_proc
{
- int fv, nv; /* First, last, # of values. */
+ int fv, nv; /* First, # of values. */
};
/* Sort order. */
int order; /* SRT_ASCEND or SRT_DESCEND. */
};
-/* MODIFY VARS private data. */
-struct modify_vars_proc
- {
- char new_name[9]; /* Variable's new name. */
- int drop_this_var; /* 0=keep this var, 1=drop this var. */
- struct variable *next; /* Next in linked list. */
- };
-
/* MEANS private data. */
struct means_proc
{
char name[9]; /* As a string. */
int index; /* Index into its dictionary's var[]. */
int type; /* NUMERIC or ALPHA. */
- int foo; /* Used for temporary storage. */
/* Also important but parse_variables() doesn't need it. Still,
check before reordering. */
int width; /* Size of string variables in chars. */
int fv, nv; /* Index into `value's, number of values. */
- int left; /* 0=do not LEAVE, 1=LEAVE. */
+ int left; /* 0=reinitialize each case, 1=don't. */
/* Missing values. */
int miss_type; /* One of the MISSING_* constants. */
char *label; /* Variable label. */
/* Per-procedure info. */
+ void *aux;
struct get_proc get;
union
{
struct list_proc lst;
struct means_proc mns;
struct sort_cases_proc srt;
- struct modify_vars_proc mfv;
struct matrix_data_proc mxd;
struct match_files_proc mtf;
}
int compare_variables (const void *, const void *, void *);
unsigned hash_variable (const void *, void *);
+
+/* Classes of variables. */
+enum dict_class
+ {
+ DC_ORDINARY, /* Ordinary identifier. */
+ DC_SYSTEM, /* System variable. */
+ DC_SCRATCH /* Scratch variable. */
+ };
+
+enum dict_class dict_class_from_id (const char *name);
+const char *dict_class_to_name (enum dict_class dict_class);
+\f
+/* Vector of variables. */
+struct vector
+ {
+ int idx; /* Index for dict_get_vector(). */
+ char name[9]; /* Name. */
+ struct variable **var; /* Vector of variables. */
+ int cnt; /* Number of variables. */
+ };
\f
/* Cases. */
/* Dictionary. */
/* Complete dictionary state. */
-struct dictionary
- {
- struct variable **var; /* Variable descriptions. */
- struct hsh_table *name_tab; /* Variables arranged by name. */
- int nvar; /* Number of variables. */
-
- int N; /* Current case limit (N command). */
- int nval; /* Number of value structures per case. */
-
- int n_splits; /* Number of SPLIT FILE variables. */
- struct variable **splits; /* List of SPLIT FILE vars. */
-
- char *label; /* File label. */
-
- int n_documents; /* Number of lines of documents. */
- char *documents; /* Documents; 80*n_documents bytes in size. */
-
- int weight_index; /* `value' index of $WEIGHT, or -1 if none.
- Call update_weighting() before using! */
- char weight_var[9]; /* Name of WEIGHT variable. */
-
- char filter_var[9]; /* Name of FILTER variable. */
- /* Do not make another field the last field! or see
- temporary.c:restore_dictionary() before doing so! */
- };
+struct dictionary;
+
+struct dictionary *dict_create (void);
+struct dictionary *dict_clone (const struct dictionary *);
+void dict_clear (struct dictionary *);
+void dict_destroy (struct dictionary *);
+
+size_t dict_get_var_cnt (const struct dictionary *);
+struct variable *dict_get_var (const struct dictionary *, size_t idx);
+void dict_get_vars (const struct dictionary *,
+ struct variable ***vars, size_t *cnt,
+ unsigned exclude_classes);
+
+struct variable *dict_create_var (struct dictionary *, const char *,
+ int width);
+struct variable *dict_clone_var (struct dictionary *, const struct variable *,
+ const char *);
+void dict_rename_var (struct dictionary *, struct variable *, const char *);
+
+struct variable *dict_lookup_var (const struct dictionary *, const char *);
+int dict_contains_var (const struct dictionary *, const struct variable *);
+void dict_delete_var (struct dictionary *, struct variable *);
+void dict_delete_vars (struct dictionary *,
+ struct variable *const *, size_t count);
+void dict_reorder_vars (struct dictionary *,
+ struct variable *const *, size_t count);
+int dict_rename_vars (struct dictionary *,
+ struct variable **, char **new_names,
+ size_t count, char **err_name);
+
+struct variable *dict_get_weight (const struct dictionary *);
+double dict_get_case_weight (const struct dictionary *, const struct ccase *);
+void dict_set_weight (struct dictionary *, struct variable *);
+
+struct variable *dict_get_filter (const struct dictionary *);
+void dict_set_filter (struct dictionary *, struct variable *);
+
+int dict_get_case_limit (const struct dictionary *);
+void dict_set_case_limit (struct dictionary *, int);
+
+int dict_get_value_cnt (const struct dictionary *);
+void dict_compact_values (struct dictionary *);
+
+struct variable *const *dict_get_split_vars (const struct dictionary *);
+size_t dict_get_split_cnt (const struct dictionary *);
+void dict_set_split_vars (struct dictionary *,
+ struct variable *const *, size_t cnt);
+
+const char *dict_get_label (const struct dictionary *);
+void dict_set_label (struct dictionary *, const char *);
+
+const char *dict_get_documents (const struct dictionary *);
+void dict_set_documents (struct dictionary *, const char *);
+
+int dict_create_vector (struct dictionary *,
+ const char *name,
+ struct variable **, size_t cnt);
+const struct vector *dict_get_vector (const struct dictionary *,
+ size_t idx);
+size_t dict_get_vector_cnt (const struct dictionary *);
+const struct vector *dict_lookup_vector (const struct dictionary *,
+ const char *name);
+void dict_clear_vectors (struct dictionary *);
+\f
+void discard_variables (void);
/* This is the active file dictionary. */
-extern struct dictionary default_dict;
+extern struct dictionary *default_dict;
\f
/* Transformation state. */
\f
/* Functions. */
-int is_varname (const char *);
-int is_dict_varname (const struct dictionary *, const char *);
-
-/* Flags for passing to fill_all_vars(). */
-enum
- {
- FV_NONE = 0, /* No flags. */
- FV_NO_SYSTEM = 001, /* Don't include system variables. */
- FV_NO_SCRATCH = 002 /* Don't include scratch variables. */
- };
-
-void fill_all_vars (struct variable ***, int *, int flags);
-
void dump_split_vars (const struct ccase *);
int is_num_user_missing (double, const struct variable *);
dup_variable (A, B, C)
#endif
-struct variable *create_variable (struct dictionary *, const char *name,
- int type, int width);
-void delete_variable (struct dictionary *, struct variable *v);
-struct variable *find_variable (const char *name);
-struct variable *find_dict_variable (const struct dictionary *,
- const char *name);
-void init_variable (struct dictionary *, struct variable *, const char *name,
- int type, int width);
-void replace_variable (struct variable *, const char *name,
- int type, int width);
-void clear_variable (struct dictionary *, struct variable *);
-void rename_variable (struct dictionary *, struct variable *v,
- const char *new_name);
-void discard_variables (void);
-void clear_default_dict (void);
-void copy_variable (struct variable *dest, const struct variable *src);
-struct variable *dup_variable (struct dictionary *dict,
- const struct variable *src, const char *name);
-
-struct variable *update_weighting (struct dictionary *);
-void stop_weighting (struct dictionary *);
-
-struct dictionary *save_dictionary (void);
-void restore_dictionary (struct dictionary *);
-void free_dictionary (struct dictionary *);
-struct dictionary *new_dictionary (int copy);
\f
/* Transformations. */
void add_transformation (struct trns_header *trns);
void cancel_transformations (void);
+\f
+struct var_set;
+
+struct var_set *var_set_create_from_dict (struct dictionary *d);
+struct var_set *var_set_create_from_array (struct variable **var, size_t);
+
+size_t var_set_get_cnt (struct var_set *vs);
+struct variable *var_set_get_var (struct var_set *vs, size_t idx);
+struct variable *var_set_lookup_var (struct var_set *vs, const char *name);
+void var_set_destroy (struct var_set *vs);
+
\f
/* Variable parsers. */
-/* Only parse_variables() supports options other than PV_APPEND,
- PV_SINGLE. */
enum
{
PV_NONE = 0, /* No options. */
- PV_SINGLE = 0001, /* Restrict to a single varname or TO use. */
+ PV_SINGLE = 0001, /* Restrict to a single name or TO use. */
PV_DUPLICATE = 0002, /* Don't merge duplicates. */
PV_APPEND = 0004, /* Append to existing list. */
PV_NO_DUPLICATE = 0010, /* Error on duplicates. */
PV_NUMERIC = 0020, /* Vars must be numeric. */
PV_STRING = 0040, /* Vars must be string. */
PV_SAME_TYPE = 00100, /* All vars must be the same type. */
- PV_NO_SCRATCH = 00200 /* Disallow scratch variables. */
+ PV_NO_SCRATCH = 00200, /* Disallow scratch variables. */
};
struct variable *parse_variable (void);
struct variable *parse_dict_variable (struct dictionary *);
-int parse_variables (struct dictionary *dict, struct variable ***v,
- int *nv, int pv_opts);
-int parse_DATA_LIST_vars (char ***names, int *nnames, int pv_opts);
-int parse_mixed_vars (char ***names, int *nnames, int pv_opts);
+int parse_variables (struct dictionary *, struct variable ***, int *,
+ int opts);
+int parse_var_set_vars (struct var_set *, struct variable ***, int *,
+ int opts);
+int parse_DATA_LIST_vars (char ***names, int *cnt, int opts);
+int parse_mixed_vars (char ***names, int *cnt, int opts);
#endif /* !var_h */
02111-1307, USA. */
#include <config.h>
+#include "var.h"
#include <assert.h>
#include <stdlib.h>
#include "alloc.h"
#include "expr.h"
#include "file-handle.h"
#include "hash.h"
-#include "inpt-pgm.h"
#include "misc.h"
#include "str.h"
-#include "var.h"
-#include "vector.h"
#include "value-labels.h"
#include "vfm.h"
#include "debug-print.h"
-/* Clear the default dictionary. Note: This is probably not what you
- want to do. Use discard_variables() instead. */
-void
-clear_default_dict (void)
-{
- int i;
-
- for (i = 0; i < default_dict.nvar; i++)
- {
- clear_variable (&default_dict, default_dict.var[i]);
- free (default_dict.var[i]);
- }
-
- assert (default_dict.splits == NULL);
-
- default_dict.nvar = 0;
- default_dict.N = 0;
- default_dict.nval = 0;
- default_handle = inline_file;
- stop_weighting (&default_dict);
-}
-
/* Discards all the current state in preparation for a data-input
command like DATA LIST or GET. */
void
discard_variables (void)
{
- clear_default_dict ();
-
+ dict_clear (default_dict);
+ default_handle = inline_file;
+
n_lag = 0;
if (vfm_source)
ctl_stack = NULL;
- free (vec);
- vec = NULL;
- nvec = 0;
-
expr_free (process_if_expr);
process_if_expr = NULL;
pgm_state = STATE_INIT;
}
-/* Find and return the variable in default_dict having name NAME, or
- NULL if no such variable exists in default_dict. */
-struct variable *
-find_variable (const char *name)
-{
- return hsh_find (default_dict.name_tab, name);
-}
-
-/* Find and return the variable in dictionary D having name NAME, or
- NULL if no such variable exists in D. */
-struct variable *
-find_dict_variable (const struct dictionary *d, const char *name)
-{
- return hsh_find (d->name_tab, name);
-}
-
-/* Creates a variable named NAME in dictionary DICT having type TYPE
- (ALPHA or NUMERIC) and, if type==ALPHA, width WIDTH. Returns a
- pointer to the newly created variable if successful. On failure
- (which indicates that a variable having the specified name already
- exists), returns NULL. */
-struct variable *
-create_variable (struct dictionary *dict, const char *name,
- int type, int width)
-{
- if (find_dict_variable (dict, name))
- return NULL;
-
- {
- struct variable *new_var;
-
- dict->var = xrealloc (dict->var, (dict->nvar + 1) * sizeof *dict->var);
- new_var = dict->var[dict->nvar] = xmalloc (sizeof *new_var);
-
- new_var->index = dict->nvar;
- dict->nvar++;
-
- init_variable (dict, new_var, name, type, width);
-
- return new_var;
- }
-}
-
-#if GLOBAL_DEBUGGING
-/* For situations in which we know that there are no variables with an
- identical name in the dictionary. */
-struct variable *
-force_create_variable (struct dictionary *dict, const char *name,
- int type, int width)
-{
- struct variable *new_var = create_variable (dict, name, type, width);
- assert (new_var != NULL);
- return new_var;
-}
-
-/* For situations in which we know that there are no variables with an
- identical name in the dictionary. */
-struct variable *
-force_dup_variable (struct dictionary *dict, const struct variable *src,
- const char *name)
-{
- struct variable *new_var = dup_variable (dict, src, name);
- assert (new_var != NULL);
- return new_var;
-}
-#endif
-
-/* Delete variable V from DICT. It should only be used when there are
- guaranteed to be absolutely NO REFERENCES to it, for instance in
- the very same function that created it. */
-void
-delete_variable (struct dictionary *dict, struct variable *v)
-{
- int i;
-
- clear_variable (dict, v);
- dict->nvar--;
- for (i = v->index; i < dict->nvar; i++)
- {
- dict->var[i] = dict->var[i + 1];
- dict->var[i]->index = i;
- }
- free (v);
-}
-
-/* Initialize fields in variable V inside dictionary D with name NAME,
- type TYPE, and width WIDTH. Initializes some other fields too. */
-static inline void
-common_init_stuff (struct dictionary *dict, struct variable *v,
- const char *name, int type, int width)
-{
- if (v->name != name)
- /* Avoid problems with overlap. */
- strcpy (v->name, name);
-
- hsh_force_insert (dict->name_tab, v);
-
- v->type = type;
- v->left = name[0] == '#';
- v->width = type == NUMERIC ? 0 : width;
- v->miss_type = MISSING_NONE;
- if (v->type == NUMERIC)
- {
- v->print.type = FMT_F;
- v->print.w = 8;
- v->print.d = 2;
- }
- else
- {
- v->print.type = FMT_A;
- v->print.w = v->width;
- v->print.d = 0;
- }
- v->write = v->print;
-}
-
-/* Initialize (for the first time) a variable V in dictionary DICT
- with name NAME, type TYPE, and width WIDTH. */
-void
-init_variable (struct dictionary *dict, struct variable *v, const char *name,
- int type, int width)
-{
- common_init_stuff (dict, v, name, type, width);
- v->nv = type == NUMERIC ? 1 : DIV_RND_UP (width, 8);
- v->fv = dict->nval;
- dict->nval += v->nv;
- v->label = NULL;
- v->val_labs = val_labs_create (width);
- v->get.fv = -1;
-
- if (vfm_source == &input_program_source
- || vfm_source == &file_type_source)
- {
- size_t nbytes = DIV_RND_UP (v->fv + 1, 4);
- unsigned val = 0;
-
- if (inp_init_size < nbytes)
- {
- inp_init = xrealloc (inp_init, nbytes);
- memset (&inp_init[inp_init_size], 0, nbytes - inp_init_size);
- inp_init_size = nbytes;
- }
-
- if (v->type == ALPHA)
- val |= INP_STRING;
- if (v->left)
- val |= INP_LEFT;
- inp_init[v->fv / 4] |= val << ((unsigned) (v->fv) % 4 * 2);
- }
-}
-
-/* Replace variable V in default_dict with a different variable having
- name NAME, type TYPE, and width WIDTH. */
-void
-replace_variable (struct variable *v, const char *name, int type, int width)
-{
- int nv;
-
- assert (v && name && (type == NUMERIC || type == ALPHA) && width >= 0
- && (type == ALPHA || width == 0));
- clear_variable (&default_dict, v);
- common_init_stuff (&default_dict, v, name, type, width);
-
- nv = (type == NUMERIC) ? 1 : DIV_RND_UP (width, 8);
- if (nv > v->nv)
- {
- v->fv = v->nv = 0;
- v->fv = default_dict.nval;
- default_dict.nval += nv;
- }
- v->nv = nv;
-}
-
-/* Changes the name of variable V in dictionary DICT to name NEW_NAME.
- NEW_NAME must be known not to already exist in dictionary DICT. */
-void
-rename_variable (struct dictionary * dict, struct variable *v,
- const char *new_name)
-{
- assert (dict && dict->name_tab && v && new_name);
- hsh_delete (dict->name_tab, v);
- strncpy (v->name, new_name, 9);
- hsh_force_insert (dict->name_tab, v);
-}
-
-/* Delete the contents of variable V within dictionary DICT. Does not
- remove the variable from the vector of variables in the dictionary.
- Use with caution. */
-void
-clear_variable (struct dictionary *dict, struct variable *v)
-{
- assert (dict != NULL);
- assert (v != NULL);
-
- if (dict->name_tab != NULL)
- hsh_force_delete (dict->name_tab, v);
-
- val_labs_clear (v->val_labs);
-
- if (v->label)
- {
- free (v->label);
- v->label = NULL;
- }
-
- if (dict->splits)
- {
- struct variable **iter, **trailer;
-
- for (trailer = iter = dict->splits; *iter; iter++)
- if (*iter != v)
- *trailer++ = *iter;
- else
- dict->n_splits--;
-
- *trailer = NULL;
-
- if (dict->n_splits == 0)
- {
- free (dict->splits);
- dict->splits = NULL;
- }
- }
-}
-
-/* Creates a new variable in dictionary DICT, whose properties are
- copied from variable SRC, and returns a pointer to the new variable
- of name NAME, if successful. If unsuccessful (which only happens
- if a variable of the same name NAME exists in DICT), returns
- NULL. */
-struct variable *
-dup_variable (struct dictionary *dict, const struct variable *src,
- const char *name)
-{
- if (find_dict_variable (dict, name))
- return NULL;
-
- {
- struct variable *new_var;
-
- dict->var = xrealloc (dict->var, (dict->nvar + 1) * sizeof *dict->var);
- new_var = dict->var[dict->nvar] = xmalloc (sizeof *new_var);
-
- new_var->index = dict->nvar;
- new_var->foo = -1;
- new_var->get.fv = -1;
- new_var->get.nv = -1;
- dict->nvar++;
-
- copy_variable (new_var, src);
-
- assert (new_var->nv >= 0);
- new_var->fv = dict->nval;
- dict->nval += new_var->nv;
-
- strcpy (new_var->name, name);
- hsh_force_insert (dict->name_tab, new_var);
-
- return new_var;
- }
-}
-
-
/* Return nonzero only if X is a user-missing value for numeric
variable V. */
inline int
#endif
#endif
+#include "var.h"
#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
#include "lexer.h"
#include "misc.h"
#include "str.h"
-#include "var.h"
-/* Allocates an array at *V to contain all the variables in
- default_dict. If FV_NO_SYSTEM is set in FLAGS then system
- variables will not be included. If FV_NO_SCRATCH is set in FLAGS
- then scratch variables will not be included. *C is set to the
- number of variables in *V. */
-void
-fill_all_vars (struct variable ***varlist, int *c, int flags)
+static struct variable *
+parse_vs_variable (struct var_set *vs)
{
- int i;
+ struct variable *vp;
- *varlist = xmalloc (default_dict.nvar * sizeof **varlist);
- if (flags == FV_NONE)
+ if (token != T_ID)
{
- *c = default_dict.nvar;
- for (i = 0; i < default_dict.nvar; i++)
- (*varlist)[i] = default_dict.var[i];
+ lex_error ("expecting variable name");
+ return NULL;
}
- else
- {
- *c = 0;
-
- for (i = 0; i < default_dict.nvar; i++)
- {
- struct variable *v = default_dict.var[i];
- if ((flags & FV_NO_SYSTEM) && v->name[0] == '$')
- continue;
- if ((flags & FV_NO_SCRATCH) && v->name[0] == '#')
- continue;
-
- (*varlist)[*c] = v;
- (*c)++;
- }
-
- if (*c != default_dict.nvar)
- *varlist = xrealloc (*varlist, *c * sizeof **varlist);
- }
-}
+ vp = var_set_lookup_var (vs, tokid);
+ if (vp == NULL)
+ msg (SE, _("%s is not a variable name."), tokid);
+ lex_get ();
-int
-is_varname (const char *s)
-{
- return hsh_find (default_dict.name_tab, s) != NULL;
+ return vp;
}
-int
-is_dict_varname (const struct dictionary *dict, const char *s)
+struct variable *
+parse_dict_variable (struct dictionary *d)
{
- return hsh_find (dict->name_tab, s) != NULL;
+ struct var_set *vs = var_set_create_from_dict (d);
+ struct variable *var = parse_vs_variable (vs);
+ var_set_destroy (vs);
+ return var;
}
struct variable *
parse_variable (void)
{
- struct variable *vp;
+ return parse_dict_variable (default_dict);
+}
- if (token != T_ID)
+
+enum dict_class
+dict_class_from_id (const char *name)
+{
+ assert (name != NULL);
+
+ switch (name[0])
{
- lex_error ("expecting variable name");
- return NULL;
+ default:
+ return DC_ORDINARY;
+ case '$':
+ return DC_SYSTEM;
+ case '#':
+ return DC_SCRATCH;
}
- vp = find_variable (tokid);
- if (!vp)
- msg (SE, _("%s is not declared as a variable."), tokid);
- lex_get ();
- return vp;
}
-struct variable *
-parse_dict_variable (struct dictionary * dict)
+const char *
+dict_class_to_name (enum dict_class dict_class)
{
- struct variable *vp;
-
- if (token != T_ID)
+ switch (dict_class)
{
- lex_error ("expecting variable name");
- return NULL;
+ case DC_ORDINARY:
+ return "ordinary";
+ case DC_SYSTEM:
+ return "system";
+ case DC_SCRATCH:
+ return "scratch";
+ default:
+ assert (0);
}
+}
- vp = hsh_find (dict->name_tab, tokid);
- if (!vp)
- msg (SE, _("%s is not a variable name."), tokid);
- lex_get ();
+int
+parse_variables (struct dictionary *d, struct variable ***var, int *cnt,
+ int opts)
+{
+ struct var_set *vs;
+ int success;
- return vp;
+ assert (d != NULL);
+ assert (var != NULL);
+ assert (cnt != NULL);
+
+ vs = var_set_create_from_dict (d);
+ success = parse_var_set_vars (vs, var, cnt, opts);
+ var_set_destroy (vs);
+ return success;
}
-/* Returns the dictionary class of an identifier based on its
- first letter: `X' if is an ordinary identifier, `$' if it
- designates a system variable, `#' if it designates a scratch
- variable. */
-#define id_dict(C) \
- ((C) == '$' ? '$' : ((C) == '#' ? '#' : 'X'))
-
-/* FIXME: One interesting variation in the case of PV_APPEND would be
- to keep the bitmap, reducing time required to an actual O(n log n)
- instead of having to reproduce the bitmap *every* *single* *time*.
- Later though. (Another idea would be to keep a marker bit in each
- variable.) */
/* Note that if parse_variables() returns 0, *v is free()'d.
Conversely, if parse_variables() returns non-zero, then *nv is
nonzero and *v is non-NULL. */
int
-parse_variables (struct dictionary * dict, struct variable *** v, int *nv, int pv_opts)
+parse_var_set_vars (struct var_set *vs,
+ struct variable ***v, int *nv,
+ int pv_opts)
{
+ size_t vs_var_cnt;
int i;
- int nbytes;
- unsigned char *bits;
+ char *included;
struct variable *v1, *v2;
int count, mv;
- int scratch; /* Dictionary we're reading from. */
- int delayed_fail = 0;
+ enum dict_class dict_class;
+
+ assert (vs != NULL);
+ assert (v != NULL);
+ assert (nv != NULL);
+
+ /* At most one of PV_NUMERIC, PV_STRING, PV_SAME_TYPE may be
+ specified. */
+ assert ((((pv_opts & PV_NUMERIC) != 0)
+ + ((pv_opts & PV_STRING) != 0)
+ + ((pv_opts & PV_SAME_TYPE) != 0)) <= 1);
- if (dict == NULL)
- dict = &default_dict;
+ /* PV_DUPLICATE and PV_NO_DUPLICATE are incompatible. */
+ assert (!(pv_opts & PV_DUPLICATE) || !(pv_opts & PV_NO_DUPLICATE));
+
+ vs_var_cnt = var_set_get_cnt (vs);
if (!(pv_opts & PV_APPEND))
{
else
mv = *nv;
-#if GLOBAL_DEBUGGING
- {
- int corrupt = 0;
- int i;
-
- for (i = 0; i < dict->nvar; i++)
- if (dict->var[i]->index != i)
- {
- printf ("%s index corruption: variable %s\n",
- dict == &default_dict ? "default_dict" : "aux dict",
- dict->var[i]->name);
- corrupt = 1;
- }
-
- assert (!corrupt);
- }
-#endif
-
- nbytes = DIV_RND_UP (dict->nvar, 8);
if (!(pv_opts & PV_DUPLICATE))
{
- bits = local_alloc (nbytes);
- memset (bits, 0, nbytes);
+ included = xmalloc (vs_var_cnt);
+ memset (included, 0, vs_var_cnt);
for (i = 0; i < *nv; i++)
- SET_BIT (bits, (*v)[i]->index);
+ included[(*v)[i]->index] = 1;
}
do
{
if (lex_match (T_ALL))
{
- v1 = dict->var[0];
- v2 = dict->var[dict->nvar - 1];
- count = dict->nvar;
- scratch = id_dict ('X');
+ v1 = var_set_get_var (vs, 0);
+ v2 = var_set_get_var (vs, vs_var_cnt - 1);
+ count = vs_var_cnt;
+ dict_class = DC_ORDINARY;
}
else
{
- v1 = parse_dict_variable (dict);
+ v1 = parse_vs_variable (vs);
if (!v1)
goto fail;
if (lex_match (T_TO))
{
- v2 = parse_dict_variable (dict);
+ enum dict_class dict_class_2;
+
+ v2 = parse_vs_variable (vs);
if (!v2)
{
lex_error ("expecting variable name");
goto fail;
}
- scratch = id_dict (v1->name[0]);
- if (scratch != id_dict (v2->name[0]))
+ dict_class = dict_class_from_id (v1->name);
+ dict_class_2 = dict_class_from_id (v2->name);
+ if (dict_class != dict_class_2)
{
msg (SE, _("When using the TO keyword to specify several "
- "variables, both variables must be from "
- "the same variable dictionaries, of either "
- "ordinary, scratch, or system variables. "
- "%s and %s are from different dictionaries."),
- v1->name, v2->name);
+ "variables, both variables must be from "
+ "the same variable dictionaries, of either "
+ "ordinary, scratch, or system variables. "
+ "%s is a %s variable, whereas %s is %s."),
+ v1->name, dict_class_to_name (dict_class),
+ v2->name, dict_class_to_name (dict_class_2));
goto fail;
}
}
{
v2 = v1;
count = 1;
- scratch = id_dict (v1->name[0]);
+ dict_class = dict_class_from_id (v1->name);
}
- if (scratch == id_dict ('#') && (pv_opts & PV_NO_SCRATCH))
+ if (dict_class == DC_SCRATCH && (pv_opts & PV_NO_SCRATCH))
{
msg (SE, _("Scratch variables (such as %s) are not allowed "
"here."), v1->name);
*v = xrealloc (*v, mv * sizeof **v);
}
+ /* Add v1...v2 to the list. */
for (i = v1->index; i <= v2->index; i++)
{
- struct variable *add = dict->var[i];
+ struct variable *add = var_set_get_var (vs, i);
/* Skip over other dictionaries. */
- if (scratch != id_dict (add->name[0]))
+ if (dict_class != dict_class_from_id (add->name))
continue;
+ /* Different kinds of errors. */
if ((pv_opts & PV_NUMERIC) && add->type != NUMERIC)
- {
- delayed_fail = 1;
- msg (SW, _("%s is not a numeric variable. It will not be "
- "included in the variable list."), add->name);
- }
+ msg (SW, _("%s is not a numeric variable. It will not be "
+ "included in the variable list."), add->name);
else if ((pv_opts & PV_STRING) && add->type != ALPHA)
- {
- delayed_fail = 1;
- msg (SE, _("%s is not a string variable. It will not be "
- "included in the variable list."), add->name);
- }
- else if ((pv_opts & PV_SAME_TYPE) && *nv && add->type != (*v)[0]->type)
- {
- delayed_fail = 1;
- msg (SE, _("%s and %s are not the same type. All variables in "
- "this variable list must be of the same type. %s "
- "will be omitted from list."),
- (*v)[0]->name, add->name, add->name);
- }
- else if ((pv_opts & PV_NO_DUPLICATE) && TEST_BIT (bits, add->index))
- {
- delayed_fail = 1;
- msg (SE, _("Variable %s appears twice in variable list."),
- add->name);
- }
- else if ((pv_opts & PV_DUPLICATE) || !TEST_BIT (bits, add->index))
- {
- (*v)[(*nv)++] = dict->var[i];
- if (!(pv_opts & PV_DUPLICATE))
- SET_BIT (bits, add->index);
- }
+ msg (SE, _("%s is not a string variable. It will not be "
+ "included in the variable list."), add->name);
+ else if ((pv_opts & PV_SAME_TYPE) && *nv
+ && add->type != (*v)[0]->type)
+ msg (SE, _("%s and %s are not the same type. All variables in "
+ "this variable list must be of the same type. %s "
+ "will be omitted from list."),
+ (*v)[0]->name, add->name, add->name);
+ else if ((pv_opts & PV_NO_DUPLICATE) && included[add->index])
+ msg (SE, _("Variable %s appears twice in variable list."),
+ add->name);
+ else {
+ /* Success--add the variable to the list. */
+ if ((pv_opts & PV_DUPLICATE) || !included[add->index])
+ {
+ (*v)[(*nv)++] = var_set_get_var (vs, i);
+ if (!(pv_opts & PV_DUPLICATE))
+ included[add->index] = 1;
+ }
+
+ /* Next. */
+ continue;
+ }
+
+ /* Arrive here only on failure. */
+ if (pv_opts & PV_SINGLE)
+ goto fail;
}
+ /* We finished adding v1...v2 to the list. */
if (pv_opts & PV_SINGLE)
- {
- if (delayed_fail)
- goto fail;
- else
- return 1;
- }
+ return 1;
lex_match (',');
}
- while ((token == T_ID && is_dict_varname (dict, tokid)) || token == T_ALL);
+ while ((token == T_ID && var_set_lookup_var (vs, tokid) != NULL)
+ || token == T_ALL);
if (!(pv_opts & PV_DUPLICATE))
- local_free (bits);
- if (!nv)
+ free (included);
+ if (!*nv)
goto fail;
return 1;
*v = NULL;
*nv = 0;
if (!(pv_opts & PV_DUPLICATE))
- local_free (bits);
+ free (included);
return 0;
}
char *root1, *root2;
int success = 0;
+ assert (names != NULL);
+ assert (nnames != NULL);
+ assert ((pv_opts & ~(PV_APPEND | PV_SINGLE
+ | PV_NO_SCRATCH | PV_NO_DUPLICATE)) == 0);
+ /* FIXME: PV_NO_DUPLICATE is not implemented. */
+
if (pv_opts & PV_APPEND)
nvar = mvar = *nnames;
else
/* Parses a list of variables where some of the variables may be
existing and the rest are to be created. Same args as
- parse_variables(). */
+ parse_DATA_LIST_vars(). */
int
parse_mixed_vars (char ***names, int *nnames, int pv_opts)
{
int i;
+ assert (names != NULL);
+ assert (nnames != NULL);
+ assert ((pv_opts & ~PV_APPEND) == 0);
+
if (!(pv_opts & PV_APPEND))
{
*names = NULL;
}
while (token == T_ID || token == T_ALL)
{
- if (token == T_ALL || is_varname (tokid))
+ if (token == T_ALL || dict_lookup_var (default_dict, tokid) != NULL)
{
struct variable **v;
int nv;
- if (!parse_variables (NULL, &v, &nv, PV_NONE))
+ if (!parse_variables (default_dict, &v, &nv, PV_NONE))
goto fail;
*names = xrealloc (*names, (*nnames + nv) * sizeof **names);
for (i = 0; i < nv; i++)
*nnames = 0;
return 0;
}
+\f
+struct var_set
+ {
+ size_t (*get_cnt) (struct var_set *);
+ struct variable *(*get_var) (struct var_set *, size_t idx);
+ struct variable *(*lookup_var) (struct var_set *, const char *);
+ void (*destroy) (struct var_set *);
+ void *aux;
+ };
+
+size_t
+var_set_get_cnt (struct var_set *vs)
+{
+ assert (vs != NULL);
+
+ return vs->get_cnt (vs);
+}
+
+struct variable *
+var_set_get_var (struct var_set *vs, size_t idx)
+{
+ assert (vs != NULL);
+ assert (idx < var_set_get_cnt (vs));
+
+ return vs->get_var (vs, idx);
+}
+
+struct variable *
+var_set_lookup_var (struct var_set *vs, const char *name)
+{
+ assert (vs != NULL);
+ assert (name != NULL);
+ assert (strlen (name) < 9);
+
+ return vs->lookup_var (vs, name);
+}
+
+void
+var_set_destroy (struct var_set *vs)
+{
+ if (vs != NULL)
+ vs->destroy (vs);
+}
+\f
+static size_t
+dict_var_set_get_cnt (struct var_set *vs)
+{
+ struct dictionary *d = vs->aux;
+
+ return dict_get_var_cnt (d);
+}
+
+static struct variable *
+dict_var_set_get_var (struct var_set *vs, size_t idx)
+{
+ struct dictionary *d = vs->aux;
+
+ return dict_get_var (d, idx);
+}
+
+static struct variable *
+dict_var_set_lookup_var (struct var_set *vs, const char *name)
+{
+ struct dictionary *d = vs->aux;
+
+ return dict_lookup_var (d, name);
+}
+
+static void
+dict_var_set_destroy (struct var_set *vs)
+{
+ free (vs);
+}
+
+struct var_set *
+var_set_create_from_dict (struct dictionary *d)
+{
+ struct var_set *vs = xmalloc (sizeof *vs);
+ vs->get_cnt = dict_var_set_get_cnt;
+ vs->get_var = dict_var_set_get_var;
+ vs->lookup_var = dict_var_set_lookup_var;
+ vs->destroy = dict_var_set_destroy;
+ vs->aux = d;
+ return vs;
+}
+\f
+struct array_var_set
+ {
+ struct variable **var;
+ size_t var_cnt;
+ struct hsh_table *name_tab;
+ };
+
+static size_t
+array_var_set_get_cnt (struct var_set *vs)
+{
+ struct array_var_set *avs = vs->aux;
+
+ return avs->var_cnt;
+}
+
+static struct variable *
+array_var_set_get_var (struct var_set *vs, size_t idx)
+{
+ struct array_var_set *avs = vs->aux;
+
+ return avs->var[idx];
+}
+
+static struct variable *
+array_var_set_lookup_var (struct var_set *vs, const char *name)
+{
+ struct array_var_set *avs = vs->aux;
+ struct variable v;
+
+ strcpy (v.name, name);
+
+ return hsh_find (avs->name_tab, &v);
+}
+
+static void
+array_var_set_destroy (struct var_set *vs)
+{
+ struct array_var_set *avs = vs->aux;
+
+ hsh_destroy (avs->name_tab);
+ free (avs);
+ free (vs);
+}
+
+struct var_set *
+var_set_create_from_array (struct variable **var, size_t var_cnt)
+{
+ struct var_set *vs;
+ struct array_var_set *avs;
+ size_t i;
+
+ vs = xmalloc (sizeof *vs);
+ vs->get_cnt = array_var_set_get_cnt;
+ vs->get_var = array_var_set_get_var;
+ vs->lookup_var = array_var_set_lookup_var;
+ vs->destroy = array_var_set_destroy;
+ vs->aux = avs = xmalloc (sizeof *avs);
+ avs->var = var;
+ avs->var_cnt = var_cnt;
+ avs->name_tab = hsh_create (2 * var_cnt,
+ compare_variables, hash_variable, NULL,
+ NULL);
+ for (i = 0; i < var_cnt; i++)
+ if (hsh_insert (avs->name_tab, var[i]) != NULL)
+ {
+ var_set_destroy (vs);
+ return NULL;
+ }
+
+ return vs;
+}
#include "misc.h"
#include "str.h"
#include "var.h"
-#include "vector.h"
-
-/* Vectors created on VECTOR. */
-struct vector *vec;
-
-/* Number of vectors in vec. */
-int nvec;
int
cmd_vector (void)
/* Maximum allocated position for vecnames, plus one position. */
char *endp = NULL;
- /* Variables on list (long form only). */
- struct variable **v = NULL;
- int nv;
-
lex_match_id ("VECTOR");
cp = vecnames = xmalloc (256);
goto fail;
}
- if (find_vector (tokid))
+ if (dict_lookup_vector (default_dict, tokid))
{
msg (SE, _("There is already a vector with name %s."), tokid);
goto fail;
if (lex_match ('='))
{
/* Long form. */
+ struct variable **v;
+ int nv;
if (strchr (vecnames, '\0')[1])
{
goto fail;
}
- if (!parse_variables (NULL, &v, &nv, PV_SAME_TYPE | PV_DUPLICATE))
+ if (!parse_variables (default_dict, &v, &nv,
+ PV_SAME_TYPE | PV_DUPLICATE))
goto fail;
- vec = xrealloc (vec, sizeof *vec * (nvec + 1));
- vec[nvec].index = nvec;
- strcpy (vec[nvec].name, vecnames);
- vec[nvec].v = v;
- vec[nvec].nv = nv;
- nvec++;
- v = NULL; /* prevent block from being freed on error */
+ dict_create_vector (default_dict, vecnames, v, nv);
+ free (v);
}
else if (lex_match ('('))
{
/* Name of an individual variable to be created. */
char name[9];
+ /* Vector variables. */
+ struct variable **v;
+ int nv;
+
if (!lex_force_int ())
return CMD_FAILURE;
nv = lex_integer ();
for (i = 0; i < nv; i++)
{
sprintf (name, "%s%d", cp, i + 1);
- if (is_varname (name))
+ if (dict_lookup_var (default_dict, name))
{
msg (SE, _("There is already a variable named %s."), name);
goto fail;
}
/* Finally create the variables and vectors. */
- vec = xrealloc (vec, sizeof *vec * (nvec + nv));
+ v = xmalloc (nv * sizeof *v);
for (cp = vecnames; *cp;)
{
- vec[nvec].index = nvec;
- strcpy (vec[nvec].name, cp);
- vec[nvec].v = xmalloc (sizeof *vec[nvec].v * nv);
- vec[nvec].nv = nv;
for (i = 0; i < nv; i++)
{
sprintf (name, "%s%d", cp, i + 1);
- vec[nvec].v[i] = force_create_variable (&default_dict, name,
- NUMERIC, 0);
- envector (vec[nvec].v[i]);
+ v[i] = dict_create_var (default_dict, name, 0);
+ assert (v[i] != NULL);
+ envector (v[i]);
}
- nvec++;
+ if (!dict_create_vector (default_dict, cp, v, nv))
+ assert (0);
cp += strlen (cp) + 1;
}
+ free (v);
}
else
{
fail:
free (vecnames);
- free (v);
return CMD_PART_SUCCESS_MAYBE;
}
-
-/* Returns a pointer to the vector with name NAME, or NULL on
- failure. */
-struct vector *
-find_vector (const char *name)
-{
- int i;
-
- for (i = 0; i < nvec; i++)
- if (!strcmp (vec[i].name, name))
- return &vec[i];
- return NULL;
-}
+++ /dev/null
-/* PSPP - computes sample statistics.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
- Written by Ben Pfaff <blp@gnu.org>.
-
- 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 the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
-
-#if !vector_h
-#define vector_h 1
-
-/* Represents a vector as created by the VECTOR transformation. */
-struct vector
- {
- int index; /* Index into vec[]. */
- char name[9]; /* Name. */
- struct variable **v; /* Vector of variables. */
- int nv; /* Number of variables. */
- };
-
-extern struct vector *vec;
-extern int nvec;
-
-struct vector *find_vector (const char *name);
-
-#endif /* !vector_h */
#endif
#endif
+#include "vfm.h"
+#include "vfmP.h"
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include "str.h"
#include "tab.h"
#include "var.h"
-#include "vector.h"
#include "value-labels.h"
-#include "vfm.h"
-#include "vfmP.h"
/*
Virtual File Manager (vfm):
end_func = endfunc;
write_case = procedure_write_case;
- if (default_dict.n_splits && procfunc != NULL)
+ if (dict_get_split_cnt (default_dict) != 0 && procfunc != NULL)
{
virt_proc_func = procfunc;
proc_func = SPLIT_FILE_procfunc;
file--it's just a waste of time and space. */
vfm_sink_info.ncases = 0;
- vfm_sink_info.nval = default_dict.nval;
+ vfm_sink_info.nval = dict_get_value_cnt (default_dict);
vfm_sink_info.case_size = (sizeof (struct ccase)
- + (default_dict.nval - 1) * sizeof (union value));
+ + ((dict_get_value_cnt (default_dict) - 1)
+ * sizeof (union value)));
if (vfm_sink == NULL)
{
int i;
/* Count up the number of `value's that will be output. */
- for (i = 0; i < temp_dict->nvar; i++)
- if (temp_dict->var[i]->name[0] != '#')
- {
- assert (temp_dict->var[i]->nv > 0);
- count_values += temp_dict->var[i]->nv;
- }
- assert (temporary == 2 || count_values <= temp_dict->nval);
+ for (i = 0; i < dict_get_var_cnt (temp_dict); i++)
+ {
+ struct variable *v = dict_get_var (temp_dict, i);
+
+ if (v->name[0] != '#')
+ {
+ assert (v->nv > 0);
+ count_values += v->nv;
+ }
+ }
+ assert (temporary == 2 || count_values <= dict_get_value_cnt (temp_dict));
}
/* Compaction is only necessary if the number of `value's to output
differs from the number already present. */
compaction_nval = count_values;
- compaction_necessary = temporary == 2 || count_values != temp_dict->nval;
+ compaction_necessary = (temporary == 2
+ || count_values != dict_get_value_cnt (temp_dict));
if (vfm_sink->init)
vfm_sink->init ();
static void
setup_filter (void)
{
- filter_index = -1;
+ filter_var = dict_get_filter (default_dict);
- if (default_dict.filter_var[0])
+ if (filter_var != NULL)
{
- struct variable *fv = find_variable (default_dict.filter_var);
-
- if (fv == NULL || fv->type == ALPHA)
- default_dict.filter_var[0] = 0;
- else
- {
- filter_index = fv->index;
- filter_var = fv;
- }
+ assert (filter_var->type == NUMERIC);
+ filter_index = filter_var->index;
+ } else {
+ filter_index = -1;
}
}
lag_head = 0;
lag_queue = xmalloc (n_lag * sizeof *lag_queue);
for (i = 0; i < n_lag; i++)
- lag_queue[i] = xmalloc (temp_dict->nval * sizeof **lag_queue);
+ lag_queue[i] = xmalloc (dict_get_value_cnt (temp_dict)
+ * sizeof **lag_queue);
}
/* There is a lot of potential confusion in the vfm and related
if (!temporary)
{
temp_trns = n_trns;
- temp_dict = &default_dict;
+ temp_dict = default_dict;
}
/* No cases passed to the procedure yet. */
off TEMPORARY. */
if (temporary)
{
- restore_dictionary (temp_dict);
+ dict_destroy (default_dict);
+ default_dict = temp_dict;
temp_dict = NULL;
}
- /* The default dictionary assumes the compacted data size. */
- default_dict.nval = compaction_nval;
+ /* Finish compaction. */
+ if (compaction_necessary)
+ finish_compaction ();
/* Old data sink --> New data source. */
if (vfm_source && vfm_source->destroy_source)
/* Old data sink is gone now. */
vfm_sink = NULL;
- /* Finish compaction. */
- if (compaction_necessary)
- finish_compaction ();
+ /* Cancel TEMPORARY. */
cancel_temporary ();
/* Free temporary cases. */
process_if_expr = NULL;
/* Cancel FILTER if temporary. */
- if (filter_index != -1 && !FILTER_before_TEMPORARY)
- default_dict.filter_var[0] = 0;
+ if (filter_var != NULL && !FILTER_before_TEMPORARY)
+ dict_set_filter (default_dict, NULL);
/* Cancel transformations. */
cancel_transformations ();
vec_clear (&reinit_blanks);
/* Turn off case limiter. */
- default_dict.N = 0;
+ dict_set_case_limit (default_dict, 0);
/* Clear VECTOR vectors. */
- {
- int i;
-
- for (i = 0; i < nvec; i++)
- free (vec[i].v);
- free (vec);
- vec = NULL;
- nvec = 0;
- }
+ dict_clear_vectors (default_dict);
debug_printf (("vfm: procedure complete\n\n"));
}
{
if (lag_count < n_lag)
lag_count++;
- memcpy (lag_queue[lag_head], temp_case, sizeof (union value) * temp_dict->nval);
+ memcpy (lag_queue[lag_head], temp_case,
+ sizeof (union value) * dict_get_value_cnt (temp_dict));
if (++lag_head >= n_lag)
lag_head = 0;
}
vfm_sink_info.ncases++;
vfm_sink->write ();
- if (default_dict.N)
- more_cases = vfm_sink_info.ncases < default_dict.N;
+ if (dict_get_case_limit (default_dict))
+ more_cases = (vfm_sink_info.ncases
+ < dict_get_case_limit (default_dict));
}
/* Are we done? */
static void
dump_splits (struct ccase *c)
{
- struct variable **iter;
+ struct variable *const *split;
struct tab_table *t;
+ size_t split_cnt;
int i;
- t = tab_create (3, default_dict.n_splits + 1, 0);
+ split_cnt = dict_get_split_cnt (default_dict);
+ t = tab_create (3, split_cnt + 1, 0);
tab_dim (t, tab_natural_dimensions);
- tab_vline (t, TAL_1 | TAL_SPACING, 1, 0, default_dict.n_splits);
- tab_vline (t, TAL_1 | TAL_SPACING, 2, 0, default_dict.n_splits);
+ tab_vline (t, TAL_1 | TAL_SPACING, 1, 0, split_cnt);
+ tab_vline (t, TAL_1 | TAL_SPACING, 2, 0, split_cnt);
tab_text (t, 0, 0, TAB_NONE, _("Variable"));
tab_text (t, 1, 0, TAB_LEFT, _("Value"));
tab_text (t, 2, 0, TAB_LEFT, _("Label"));
- for (iter = default_dict.splits, i = 0; *iter; iter++, i++)
+ split = dict_get_split_vars (default_dict);
+ for (i = 0; i < split_cnt; i++)
{
- struct variable *v = *iter;
+ struct variable *v = split[i];
char temp_buf[80];
const char *val_lab;
SPLIT_FILE_procfunc (struct ccase *c)
{
static struct ccase *prev_case;
- struct variable **iter;
+ struct variable *const *split;
+ size_t split_cnt;
+ size_t i;
/* The first case always begins a new series. We also need to
preserve the values of the case for later comparison. */
/* Compare the value of each SPLIT FILE variable to the values on
the previous case. */
- for (iter = default_dict.splits; *iter; iter++)
+ split = dict_get_split_vars (default_dict);
+ split_cnt = dict_get_split_cnt (default_dict);
+ for (i = 0; i < split_cnt; i++)
{
- struct variable *v = *iter;
+ struct variable *v = split[i];
switch (v->type)
{
{
int i;
int nval = 0;
+ size_t var_cnt;
assert (compaction_necessary);
/* Copy all the variables except the scratch variables from SRC to
DEST. */
- for (i = 0; i < default_dict.nvar; i++)
+ var_cnt = dict_get_var_cnt (default_dict);
+ for (i = 0; i < var_cnt; i++)
{
- struct variable *v = default_dict.var[i];
+ struct variable *v = dict_get_var (default_dict, i);
if (v->name[0] == '#')
continue;
static void
finish_compaction (void)
{
- int copy_index = 0;
- int nval = 0;
int i;
- for (i = 0; i < default_dict.nvar; i++)
+ for (i = 0; i < dict_get_var_cnt (default_dict); )
{
- struct variable *v = default_dict.var[i];
-
- if (v->name[0] == '#')
- {
- clear_variable (&default_dict, v);
- free (v);
- continue;
- }
+ struct variable *v = dict_get_var (default_dict, i);
- v->fv = nval;
- if (v->type == NUMERIC)
- nval++;
+ if (v->name[0] == '#')
+ dict_delete_var (default_dict, v);
else
- nval += DIV_RND_UP (v->width, sizeof (union value));
-
- default_dict.var[copy_index++] = v;
- }
- if (copy_index != default_dict.nvar)
- {
- default_dict.var = xrealloc (default_dict.var,
- sizeof *default_dict.var * copy_index);
- default_dict.nvar = copy_index;
+ i++;
}
+ dict_compact_values (default_dict);
}
lex_match_id ("WEIGHT");
if (lex_match_id ("OFF"))
- default_dict.weight_var[0] = 0;
+ dict_set_weight (default_dict, NULL);
else
{
struct variable *v;
return CMD_FAILURE;
}
- strcpy (default_dict.weight_var, v->name);
+ dict_set_weight (default_dict, v);
}
return lex_end_of_command ();
}
-
-#if 0 /* FIXME: dead code. */
-static int
-weight_trns_proc (any_trns * pt, ccase * c)
-{
- weight_trns *t = (weight_trns *) pt;
-
- c->data[t->dest].f = c->data[t->src].f;
- return -1;
-}
-#endif
-\f
-/* Global functions. */
-
-/* Sets the weight_index member of dictionary D to an appropriate
- value for the value of weight_var, and returns the weighting
- variable if any or NULL if none. */
-struct variable *
-update_weighting (struct dictionary * d)
-{
- if (d->weight_var[0])
- {
- struct variable *v = find_dict_variable (d, d->weight_var);
- if (v && v->type == NUMERIC)
- {
- d->weight_index = v->fv;
- return v;
- }
- else
- {
-#if GLOBAL_DEBUGGING
- printf (_("bad weighting variable, canceling\n"));
-#endif
- d->weight_var[0] = 0;
- }
- }
-
- d->weight_index = -1;
- return NULL;
-}
-
-/* Turns off case weighting for dictionary D. */
-void
-stop_weighting (struct dictionary * d)
-{
- d->weight_var[0] = 0;
-}