Sat Dec 27 16:16:49 2003 Ben Pfaff <blp@gnu.org>
authorBen Pfaff <blp@gnu.org>
Tue, 30 Dec 2003 04:42:15 +0000 (04:42 +0000)
committerBen Pfaff <blp@gnu.org>
Tue, 30 Dec 2003 04:42:15 +0000 (04:42 +0000)
* 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.

101 files changed:
ChangeLog
TODO
configure.ac
src/ChangeLog
src/Makefile.am
src/aggregate.c
src/algorithm.c
src/algorithm.h
src/alloc.c
src/apply-dict.c
src/ascii.c
src/autorecode.c
src/cmdline.c
src/cmdline.h [new file with mode: 0644]
src/command.c
src/command.def
src/command.h
src/compute.c
src/correlations.q
src/count.c
src/crosstabs.q
src/data-in.c
src/data-in.h
src/data-list.c
src/descript.q
src/dfm.c
src/dfm.h
src/dictionary.c [new file with mode: 0644]
src/do-if.c
src/error.c
src/expr-evl.c
src/expr-opt.c
src/expr-prs.c
src/file-handle.h
src/file-handle.q
src/file-type.c
src/filename.c
src/flip.c
src/format.c
src/formats.c
src/frequencies.q
src/get.c
src/getline.c
src/glob.c
src/glob.h [new file with mode: 0644]
src/groff-font.c
src/hash.c
src/heap.c
src/heap.h
src/html.c
src/inpt-pgm.c
src/inpt-pgm.h [deleted file]
src/lexer.c
src/list.q
src/loop.c
src/main.c
src/matrix-data.c
src/matrix.c
src/means.q
src/mis-val.c
src/modify-vars.c
src/numeric.c
src/output.c
src/pfm-read.c
src/pfm-write.c
src/pfm.h
src/pool.c
src/postscript.c
src/print.c
src/q2c.c
src/random.c
src/random.h
src/recode.c
src/rename-vars.c
src/repeat.c
src/repeat.h [new file with mode: 0644]
src/sel-if.c
src/set.q
src/sfm-read.c
src/sfm-write.c
src/som.c
src/sort.c
src/split-file.c
src/stats.c
src/stats.h
src/str.c
src/sysfile-info.c
src/t-test.q
src/tab.c
src/temporary.c
src/title.c
src/val-labs.c
src/value-labels.c
src/var-labs.c
src/var.h
src/vars-atr.c
src/vars-prs.c
src/vector.c
src/vector.h [deleted file]
src/vfm.c
src/weight.c

index 4049faa8997f8cd6307e2e163a05e107d58fdf05..e4d7e3b335eb8055ecdbc70c142b43c75f650c03 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+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
diff --git a/TODO b/TODO
index fd4bd6891166bdce143e518cc6116a1d96c54c2a..5f4a0d30d62b51d67f872760c55fd94f06dadb77 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,8 +1,11 @@
-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.
 
@@ -58,10 +61,6 @@ Remove ccase * argument from procfunc argument to procedure().
 
 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().
index b55a14651ab4c5ff9d2b60efd5fafdf258d8e4ea..be5cbc2033079f45ea903f3a0028cd0b1343a9ba 100644 (file)
@@ -92,7 +92,7 @@ AC_PROG_LN_S
 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
index 63c2cc61fef16edaa74f42278a83feabe41c186c..df276bd08311234ffa4ca34eb199f901f40e6af9 100644 (file)
@@ -1,3 +1,576 @@
+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.
index 2957ac492d865085e2185e9200fc3535ccb6147b..906f25cd1e02b770a6f5236f5151c9916810dabd 100644 (file)
@@ -29,23 +29,24 @@ frequencies.q list.q means.q set.q t-test.q
 
 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                   \
@@ -54,6 +55,7 @@ pspp_LDADD =  ../lib/julcal/libjulcal.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@ \
index d3f887dbd42a5a33caf1cc00522d599717ecee16..67f4985a71001f0b6a7bdba064ddb1fece8c1e1b 100644 (file)
@@ -21,7 +21,6 @@
 #include <assert.h>
 #include <stdlib.h>
 #include "alloc.h"
-#include "approx.h"
 #include "command.h"
 #include "error.h"
 #include "file-handle.h"
@@ -65,8 +64,6 @@ enum
     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. */
@@ -171,7 +168,9 @@ cmd_aggregate (void)
   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");
 
@@ -185,7 +184,7 @@ cmd_aggregate (void)
          if (seen & 1)
            {
              free (v_sort);
-             free_dictionary (agr_dict);
+             dict_destroy (agr_dict);
              msg (SE, _("OUTFILE specified multiple times."));
              return CMD_FAILURE;
            }
@@ -200,7 +199,7 @@ cmd_aggregate (void)
              if (outfile == NULL)
                {
                  free (v_sort);
-                 free_dictionary (agr_dict);
+                 dict_destroy (agr_dict);
                  return CMD_FAILURE;
                }
            }
@@ -211,7 +210,7 @@ cmd_aggregate (void)
          if (!lex_match_id ("COLUMNWISE"))
            {
              free (v_sort);
-             free_dictionary (agr_dict);
+             dict_destroy (agr_dict);
              lex_error (_("while expecting COLUMNWISE"));
              return CMD_FAILURE;
            }
@@ -226,7 +225,7 @@ cmd_aggregate (void)
          if (seen & 8)
            {
              free (v_sort);
-             free_dictionary (agr_dict);
+             dict_destroy (agr_dict);
              msg (SE, _("BREAK specified multiple times."));
              return CMD_FAILURE;
            }
@@ -235,7 +234,7 @@ cmd_aggregate (void)
          lex_match ('=');
          if (!parse_sort_variables ())
            {
-             free_dictionary (agr_dict);
+             dict_destroy (agr_dict);
              return CMD_FAILURE;
            }
          
@@ -246,7 +245,7 @@ cmd_aggregate (void)
              {
                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);
              }
          }
@@ -268,16 +267,10 @@ cmd_aggregate (void)
 
   /* 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);
@@ -426,12 +419,14 @@ create_sysfile (void)
     {
       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;
 }
@@ -442,9 +437,6 @@ parse_aggregate_functions (void)
 {
   agr_first = agr_next = NULL;
 
-  /* Anticipate weighting for optimization later. */
-  update_weighting (&default_dict);
-  
   /* Parse everything. */
   for (;;)
     {
@@ -543,7 +535,7 @@ parse_aggregate_functions (void)
            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;
          }
 
@@ -624,7 +616,7 @@ parse_aggregate_functions (void)
 
            if (src)
              {
-               int output_type;
+               int output_width;
 
                agr_next->src = src[i];
                
@@ -634,23 +626,19 @@ parse_aggregate_functions (void)
                    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))
                      {
@@ -661,7 +649,7 @@ parse_aggregate_functions (void)
                  }
              } 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)
@@ -752,7 +740,7 @@ free_aggregate_functions (void)
   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;
@@ -837,7 +825,7 @@ aggregate_single_case (struct ccase *input, struct ccase *output)
        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;
@@ -891,8 +879,9 @@ static void
 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)
@@ -905,12 +894,10 @@ accumulate_aggregate_info (struct ccase *input)
          {
            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;
              }
@@ -922,190 +909,95 @@ accumulate_aggregate_info (struct ccase *input)
        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;
@@ -1113,7 +1005,6 @@ accumulate_aggregate_info (struct ccase *input)
              }
            break;
          case FIRST | FSTRING:
-         case FIRST | FSTRING | FWEIGHT:
            if (iter->int1 == 0)
              {
                memcpy (iter->string, v->s, iter->src->width);
@@ -1121,12 +1012,10 @@ accumulate_aggregate_info (struct ccase *input)
              }
            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;
@@ -1136,12 +1025,10 @@ accumulate_aggregate_info (struct ccase *input)
     } 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:
@@ -1194,58 +1081,37 @@ dump_aggregate_info (struct ccase *output)
        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:
@@ -1256,56 +1122,35 @@ dump_aggregate_info (struct ccase *output)
          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:
@@ -1324,10 +1169,8 @@ initialize_aggregate_info (void)
 
   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;
@@ -1382,9 +1225,9 @@ write_case_to_sfm (void)
   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)
        {
index ba4413da749f743070a0cddd21a16af32d6fcf3e..8a569749e6ddfd85fc89d4a7a24367bd02e67b37 100644 (file)
  * 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,
@@ -129,68 +170,6 @@ sort_unique (void *array, size_t count, size_t size,
   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
@@ -280,7 +259,7 @@ copy_if (const void *array, size_t count, size_t size,
   const unsigned char *last = input + size * count;
   unsigned char *output = result;
   
-  while (input <= last)
+  while (input < last)
     {
       if (predicate (input, aux)) 
         {
@@ -311,6 +290,50 @@ not (const void *data, void *pred_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
@@ -391,27 +414,7 @@ lexicographical_compare (const void *array1, size_t count1,
 
   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.  */
@@ -627,3 +630,78 @@ sort (void *const pbase, size_t total_elems, size_t size,
       }
   }
 }
+\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;
+}
+
index d32b5c0737604ea6939255ad1920238361cdf5c8..441130078c46e0ec3890bf67115aaa4ccdead1e5 100644 (file)
@@ -18,6 +18,15 @@ typedef unsigned algo_random_func (unsigned max, void *aux);
 /* 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. */
@@ -57,6 +66,14 @@ size_t copy_if (const void *array, size_t count, size_t size,
                 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
@@ -83,4 +100,26 @@ int lexicographical_compare (const void *array1, size_t count1,
                              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 */
index 0dc815f71de75d8beb99abd8b29c13cffd8f6ffe..267bf2baec09c652807d24cae3a879f128c393c3 100644 (file)
@@ -18,6 +18,7 @@
    02111-1307, USA. */
 
 #include <config.h>
+#include "alloc.h"
 #include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
index 76820b7f9c41d2f0e717d7658ef65a48fa3d30f1..541d93382ddafed986cfe1811a684438573cdf85 100644 (file)
@@ -55,10 +55,10 @@ cmd_apply_dictionary (void)
   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;
 
@@ -150,6 +150,7 @@ cmd_apply_dictionary (void)
          t->miss_type = s->miss_type;
          memcpy (t->missing, s->missing, sizeof s->missing);
        }
+    skip_missing_values: ;
 
       if (s->type == NUMERIC)
        {
@@ -163,29 +164,14 @@ cmd_apply_dictionary (void)
               "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);
 
index 06addff506fe6e447548695f20410f2e41341f6e..10345005275a412eaab903f72c64a137d1353cd9 100644 (file)
@@ -182,21 +182,21 @@ static struct pool *ascii_pool;
 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};
@@ -206,7 +206,7 @@ ascii_font_sizes (struct outp_class *this unused, int *n_valid_sizes)
   return valid_sizes;
 }
 
-int
+static int
 ascii_preopen_driver (struct outp_driver *this)
 {
   struct ascii_driver_ext *x;
@@ -255,7 +255,7 @@ ascii_preopen_driver (struct outp_driver *this)
   return 1;
 }
 
-int
+static int
 ascii_postopen_driver (struct outp_driver *this)
 {
   struct ascii_driver_ext *x = this->ext;
@@ -380,7 +380,7 @@ ascii_postopen_driver (struct outp_driver *this)
   return 1;
 }
 
-int
+static int
 ascii_close_driver (struct outp_driver *this)
 {
   struct ascii_driver_ext *x = this->ext;
@@ -442,7 +442,7 @@ static struct outp_option option_tab[] =
   };
 static struct outp_option_info option_info;
 
-void
+static void
 ascii_option (struct outp_driver *this, const char *key,
              const struct string *val)
 {
@@ -667,7 +667,7 @@ preclose (struct file_ext *f)
   return 1;
 }
 
-int
+static int
 ascii_open_page (struct outp_driver *this)
 {
   struct ascii_driver_ext *x = this->ext;
@@ -726,7 +726,7 @@ expand_line (struct ascii_driver_ext *x, int i, int l)
 #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)
 {
@@ -760,7 +760,7 @@ ascii_line_horz (struct outp_driver *this, const struct rect *r,
     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)
 {
@@ -795,7 +795,7 @@ ascii_line_vert (struct outp_driver *this, const struct rect *r,
     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)
@@ -825,23 +825,9 @@ ascii_line_intersection (struct outp_driver *this, const struct rect *r,
   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)
 {
@@ -849,23 +835,23 @@ ascii_box (struct outp_driver *this unused, const struct rect *r 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;
@@ -886,7 +872,7 @@ ascii_text_set_font_by_name (struct outp_driver * this, const char *s)
     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;
@@ -894,13 +880,13 @@ ascii_text_set_font_by_position (struct outp_driver *this, int pos)
   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;
@@ -922,21 +908,21 @@ ascii_text_get_font_name (struct outp_driver *this)
   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);
@@ -1050,7 +1036,7 @@ delineate (struct outp_driver *this, struct outp_text *t, int draw)
   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);
@@ -1063,7 +1049,7 @@ ascii_text_metrics (struct outp_driver *this, struct outp_text *t)
     delineate (this, t, 0);
 }
 
-void
+static void
 ascii_text_draw (struct outp_driver *this, struct outp_text *t)
 {
   /* FIXME: orientations not supported. */
@@ -1489,7 +1475,7 @@ output_lines (struct outp_driver *this, int first, int count)
     }
 }
 
-int
+static int
 ascii_close_page (struct outp_driver *this)
 {
   static unsigned char *s;
index bec21badbfc84e35f428cc03ce5a442ec2de66bc..488361dd17c85b23eff3f9d94ef345e9d572715a 100644 (file)
@@ -98,7 +98,7 @@ cmd_autorecode (void)
   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;
@@ -126,7 +126,7 @@ cmd_autorecode (void)
     {
       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]);
@@ -157,7 +157,8 @@ cmd_autorecode (void)
 
   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);
index a1a5281c3fb89819f363a99e0273c9a0202232b1..9f1bc9796c639cc80fb97b067648770e9dbe47c8 100644 (file)
@@ -18,6 +18,7 @@
    02111-1307, USA. */
 
 #include <config.h>
+#include "cmdline.h"
 #include <assert.h>
 #include <ctype.h>
 #include <stdio.h>
diff --git a/src/cmdline.h b/src/cmdline.h
new file mode 100644 (file)
index 0000000..c381741
--- /dev/null
@@ -0,0 +1,25 @@
+/* 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 */
index d4c130aa64bce968c62d38f373d4304b243b8178..4afe70be1130a96af955f2627cbe7724e516244e 100644 (file)
@@ -36,12 +36,12 @@ char *alloca ();
 #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"
@@ -86,14 +86,6 @@ struct command
     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},
@@ -576,7 +568,7 @@ cmd_n_of_cases (void)
   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 ();
 }
index beaf77417504c630326f5c397fe03a5639cdef34..6dd88bfe94629012be08c7e23be1618e9967647a 100644 (file)
@@ -56,9 +56,7 @@ DEFCMD ("END INPUT PROGRAM",      ERRO, TRAN, ERRO, ERRO, cmd_end_input_program)
 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)
@@ -86,7 +84,7 @@ DEFCMD ("MATCH FILES",            TRAN, ERRO, TRAN, PROC, cmd_match_files)
 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)
index 0a61996d5e6b94187f02661019e7f980606590d5..b051a4be1b8773cdc8a218b095c875e2e544ebdf 100644 (file)
@@ -46,4 +46,12 @@ extern const char *cur_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 */
index d07bcb6e21d0983b61b3e5e8ad30e907ff2591c7..e299bd67f52f32100cc741cbfafdbb04c67e23cd 100644 (file)
@@ -18,6 +18,7 @@
    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. */
@@ -344,15 +262,22 @@ if_str_vec (struct trns_header * pt, struct ccase * c)
    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 != '.')
     {
@@ -365,94 +290,149 @@ parse_target_expression (struct compute_trns *c,
 
 /* 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)
 {
@@ -472,4 +452,3 @@ cmd_evaluate (void)
   
   return CMD_SUCCESS;
 }
-#endif
index e3e131fd5a9617d19562a1fac8d3242b77d15595..c7aed0ddc4b16575256125669cf1392eb2a0411d 100644 (file)
@@ -90,18 +90,19 @@ cor_custom_variables (struct cmd_correlations *cmd unused)
   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);
@@ -162,3 +163,9 @@ free_correlations_state (void)
       free (cor);
     }
 }
+
+/*
+  Local Variables:
+  mode: c
+  End:
+*/
index 7c0420def0401f8540bad79c90777420a410a2b8..02cb7838891fe415541e5d01f0d00c0683199f50 100644 (file)
@@ -135,21 +135,6 @@ static void count_trns_free (struct trns_header *);
 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)
 {
@@ -179,7 +164,7 @@ 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)
@@ -200,7 +185,8 @@ cmd_count (void)
        {
          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 ('('))
@@ -230,12 +216,15 @@ cmd_count (void)
   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
index 88c7349120f6a2b0a17fbc27ac4f219df2b5e63c..bf89d377cab49efdd3607d9eb9a2738b26b8130b 100644 (file)
@@ -134,8 +134,9 @@ static struct hsh_table *gen_tab;   /* Hash table. */
 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;
@@ -165,7 +166,6 @@ static struct pool *pl_tc;  /* For table cells. */
 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 *);
@@ -183,7 +183,7 @@ cmd_crosstabs (void)
 {
   int result = internal_cmd_crosstabs ();
 
-  free_var_dict ();
+  free (variables);
   pool_destroy (pl_tc);
   pool_destroy (pl_col);
   
@@ -194,7 +194,8 @@ cmd_crosstabs (void)
 static int
 internal_cmd_crosstabs (void)
 {
-  var_dict = NULL;
+  variables = NULL;
+  variables_cnt = 0;
   xtab = NULL;
   nxtab = 0;
   pl_tc = pool_create ();
@@ -205,12 +206,11 @@ internal_cmd_crosstabs (void)
     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;
@@ -295,45 +295,16 @@ internal_cmd_crosstabs (void)
   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;
@@ -342,20 +313,24 @@ crs_custom_tables (struct cmd_crosstabs *cmd unused)
 
   /* 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++;
 
@@ -364,7 +339,7 @@ crs_custom_tables (struct cmd_crosstabs *cmd unused)
          if (n_by < 1)
            {
              lex_error (_("expecting BY"));
-             goto lossage;
+             goto done;
            }
          else 
            break;
@@ -387,12 +362,8 @@ crs_custom_tables (struct cmd_crosstabs *cmd unused)
        {
          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]];
        }
        
        {
@@ -410,11 +381,10 @@ crs_custom_tables (struct cmd_crosstabs *cmd unused)
       }
     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;
 
@@ -424,6 +394,8 @@ crs_custom_tables (struct cmd_crosstabs *cmd unused)
     free (by_nvar);
   }
 
+  var_set_destroy (var_set);
+
   return success;
 }
 
@@ -431,9 +403,6 @@ crs_custom_tables (struct cmd_crosstabs *cmd unused)
 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."));
@@ -444,12 +413,12 @@ crs_custom_variables (struct cmd_crosstabs *cmd unused)
   
   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;
@@ -486,40 +455,22 @@ crs_custom_variables (struct cmd_crosstabs *cmd unused)
        }
       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;
 }
 
@@ -529,27 +480,25 @@ debug_print (void)
 {
   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");
     }
@@ -656,9 +605,7 @@ static int
 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;
@@ -683,7 +630,7 @@ calc_general (struct ccase *c)
                || (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;
              }
              
@@ -708,13 +655,13 @@ calc_general (struct ccase *c)
          {
            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:
@@ -728,9 +675,7 @@ static int
 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;
@@ -751,7 +696,7 @@ calc_integer (struct ccase *c)
          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;
            }
          
@@ -767,7 +712,7 @@ calc_integer (struct ccase *c)
        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: ;
@@ -2346,7 +2291,7 @@ display_directional (void)
 
 /* Returns the value of the gamma (factorial) function for an integer
    argument X. */
-double
+static double
 gamma_int (double x)
 {
   double r = 1;
@@ -2903,7 +2848,7 @@ calc_symmetric (double v[N_SYMMETRIC], double ase[N_SYMMETRIC],
                               + (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
index 95da2eed33d4aae4800570894c5c8305ec271dec..eca83d0b44a96764d18b69171a15644284ad4bee 100644 (file)
@@ -18,6 +18,7 @@
    02111-1307, USA. */
 
 #include <config.h>
+#include "data-in.h"
 #include <assert.h>
 #include <math.h>
 #include <ctype.h>
@@ -25,7 +26,6 @@
 #include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include "data-in.h"
 #include "error.h"
 #include "getline.h"
 #include "julcal/julcal.h"
index c520920522838d4e3b82f90521251ff675eefd75..c569d55c990beb9d56601b5f48583ef68ef87cb5 100644 (file)
@@ -20,6 +20,7 @@
 #if !data_in_h
 #define data_in_h 1
 
+#include <stddef.h>
 #include "format.h"
 
 /* Flags. */
index 81edf41925e4d656bcfb778a58612d15542d216f..a024b263815c5cf39a14959c891cb2360c6dd605 100644 (file)
@@ -74,7 +74,7 @@ struct dls_var_spec
     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. */
@@ -177,9 +177,12 @@ cmd_data_list (void)
          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)
@@ -513,14 +516,21 @@ fixed_parse_compatible (void)
   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);
@@ -528,8 +538,8 @@ fixed_parse_compatible (void)
        }
       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]);
@@ -554,7 +564,7 @@ fixed_parse_compatible (void)
       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;
@@ -603,9 +613,19 @@ dump_fmt_list (struct fmt_list *f)
        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 "
@@ -614,9 +634,9 @@ dump_fmt_list (struct fmt_list *f)
                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]);
@@ -631,7 +651,7 @@ dump_fmt_list (struct fmt_list *f)
            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;
@@ -782,11 +802,12 @@ parse_free (void)
   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 ('('))
@@ -808,14 +829,14 @@ parse_free (void)
 
       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]);
@@ -826,7 +847,7 @@ parse_free (void)
 
          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++)
@@ -1151,10 +1172,10 @@ read_from_data_list_list (void)
                 "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;
        }
       
index 748655ca16cba1625776dc91ea1ecb05523328e6..69134aef521087642af516bfe0761b958baca0b1 100644 (file)
@@ -288,7 +288,6 @@ cmd_descriptives (void)
     }
 
   /* Data pass! */
-  update_weighting (&default_dict);
   bad_weight = 0;
   procedure (precalc, calc, postcalc);
 
@@ -316,7 +315,7 @@ static int
 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 ('=');
@@ -326,7 +325,7 @@ dsc_custom_variables (struct cmd_descriptives *cmd unused)
       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;
@@ -345,7 +344,7 @@ dsc_custom_variables (struct cmd_descriptives *cmd unused)
              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."),
@@ -384,7 +383,7 @@ try_name (char *name)
 {
   int i;
 
-  if (is_varname (name))
+  if (dict_lookup_var (default_dict, name) != NULL)
     return 0;
   for (i = 0; i < n_variables; i++)
     {
@@ -540,9 +539,9 @@ run_z_pass (void)
          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);
@@ -602,20 +601,13 @@ calc (struct ccase * c)
   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. */
@@ -628,17 +620,17 @@ calc (struct ccase * c)
        {
          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++)
@@ -658,7 +650,7 @@ iterate:
       if (X == SYSMIS
          || (!opt[op_incl_miss] && is_num_user_missing (X, v_variables[i])))
        {
-         inf->miss += w;
+         inf->miss += weight;
          continue;
        }
 
@@ -670,19 +662,19 @@ iterate:
          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;
index 0b231208b8a686b8eb9b8dc4f64e317efeed2f26..0cfa801fcf20c6d47715042818b544496adfc981 100644 (file)
--- a/src/dfm.c
+++ b/src/dfm.c
@@ -36,6 +36,7 @@ char *alloca ();
 #endif
 
 #include <assert.h>
+#include "dfm.h"
 #include <ctype.h>
 #include <errno.h>
 #include <stdlib.h>
@@ -485,6 +486,8 @@ eof:
 char *
 dfm_get_record (struct file_handle *h, int *len)
 {
+  assert (h != NULL);
+
   if (h->class == NULL)
     {
       if (!open_file_r (h))
index ef915695f8596120dccd92079d0c56f189b11660..f561a45eee2592980a30ad0037d57d934656498c 100644 (file)
--- a/src/dfm.h
+++ b/src/dfm.h
@@ -26,6 +26,8 @@
    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);
diff --git a/src/dictionary.c b/src/dictionary.c
new file mode 100644 (file)
index 0000000..dba6bb1
--- /dev/null
@@ -0,0 +1,726 @@
+/* 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;
+}
index 88022b3b4ccf257b163e058f7e19768699c9f229..247684ec296a71dd33b0d4142eb562a4978267c0 100644 (file)
@@ -18,6 +18,7 @@
    02111-1307, USA. */
 
 #include <config.h>
+#include "do-ifP.h"
 #include <assert.h>
 #include <stdlib.h>
 #include "alloc.h"
@@ -73,8 +74,6 @@
 */
 /* *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 *);
index 181bd3c9587241e97fa69ce6cc513e1db7d5aac9..fc34d5d9deccc97052039ba6b483eb838317601b 100644 (file)
@@ -36,13 +36,13 @@ char *alloca ();
 #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"
index e750b18e4c3c6aa372572fbc0aff5bedbcfe2ada..b8991547a359ae9a43f68331d9e9c536e4288e42 100644 (file)
@@ -47,6 +47,8 @@ char *alloca ();
 #endif
 
 #include <ctype.h>
+#include "expr.h"
+#include "exprP.h"
 #include <assert.h>
 #include <math.h>
 #include <errno.h>
@@ -54,15 +56,12 @@ char *alloca ();
 #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"
 
@@ -1217,9 +1216,9 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v)
        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 "
@@ -1232,16 +1231,16 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v)
                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 "
@@ -1258,7 +1257,7 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v)
                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;
index 8724b9e017ec58482d7fba2c466e29fb5034581a..9d1537733fa0ede071e3cc2adb05f6367dd5c2b5 100644 (file)
@@ -18,6 +18,8 @@
    02111-1307, USA. */
 
 #include <config.h>
+#include "expr.h"
+#include "exprP.h"
 #include <assert.h>
 #include <math.h>
 #include <ctype.h>
@@ -27,8 +29,6 @@
 #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"
@@ -1021,9 +1021,8 @@ dump_expression (union any_node * n, struct expression * expr)
        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);
index 3d5973950695d22aa553442ee4396988b09d9f7f..046e360f1dfe610a6035a7b5e08ad31295f0affa 100644 (file)
@@ -18,6 +18,8 @@
    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. */
@@ -624,7 +623,7 @@ parse_primary (union any_node **n)
          }
 
        /* Otherwise, it must be a user variable. */
-       v = find_variable (tokid);
+       v = dict_lookup_var (default_dict, tokid);
        lex_get ();
        if (v == NULL)
          {
@@ -757,7 +756,9 @@ ternary_func (struct function * f, int x unused, union any_node ** n)
 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 ();
@@ -775,7 +776,9 @@ SYSMIS_func (struct function * f unused, int x unused, union any_node ** n)
 {
   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 ();
@@ -894,7 +897,7 @@ nary_num_func (struct function *f, int min_args, union any_node **n)
 
       /* 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;
@@ -906,7 +909,7 @@ nary_num_func (struct function *f, int min_args, union any_node **n)
            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)
            {
@@ -1221,10 +1224,10 @@ parse_function (union any_node ** n)
   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 ();
@@ -1233,7 +1236,7 @@ parse_function (union any_node ** n)
 
       *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;
 
@@ -1252,9 +1255,9 @@ parse_function (union any_node ** n)
          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);
index e1a544b482abd5915f190c739d813eef9947ecdf..b086d7870340fd7c57e6d3364f8760138f5addf7 100644 (file)
@@ -82,6 +82,9 @@ struct file_handle
    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);
index 3cc680d052fa44d78aedfa88026949c4af0d1d94..3ff35e8e85c47db1f10925c3d57a8988521b8d91 100644 (file)
    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"
index b0ed4607f06625071ff2941f30dee15ad6939e79..4181538f786dc6c80fa9e4bde68c0be8443c1cd2 100644 (file)
@@ -284,15 +284,13 @@ cmd_file_type (void)
 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. */
index 5cbbc9eab2d6ec2bbb83dc586205cd69a61d16f1..458b1c4102d93e048b1dbd9832cc4d07f7d63271 100644 (file)
@@ -36,12 +36,12 @@ char *alloca ();
 #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"
index 3a77334a76ae4f68190c58af46fd950e0682825d..d2eb197cc745de22a39c5d0546912b9c596ac07f 100644 (file)
@@ -61,12 +61,12 @@ cmd_flip (void)
   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"))
@@ -80,7 +80,7 @@ cmd_flip (void)
        }
     }
   else
-    newnames = find_variable ("CASE_LBL");
+    newnames = dict_lookup_var (default_dict, "CASE_LBL");
 
   if (newnames)
     {
@@ -101,7 +101,7 @@ cmd_flip (void)
   new_names_tail = NULL;
   procedure (NULL, NULL, NULL);
 
-  clear_default_dict ();
+  dict_clear (default_dict);
   if (!build_dictionary ())
     {
       discard_variables ();
@@ -137,7 +137,7 @@ make_new_var (char name[])
     *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. */
@@ -152,7 +152,7 @@ make_new_var (char name[])
        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;
       }
   }
@@ -165,7 +165,8 @@ make_new_var (char name[])
 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)
     {
@@ -179,10 +180,12 @@ build_dictionary (void)
       
       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
index 61b223e2ead79c70c44fd7efa6022db1cf5aa1f9..bed7241884099b14864c2c3f0e69104f8a0ee00e 100644 (file)
    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"
index aaf6f33fda0aeb30237fba147272ad63f9cee47e..9198b0ad35ce7dbdb0843d364361098cae921f64 100644 (file)
@@ -84,7 +84,7 @@ internal_cmd_formats (int which)
       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;
 
index 98f5b5802586048530278c4d119358dff0677bc5..90385935ed98400831424ff2fd04e0680a86dc51 100644 (file)
@@ -208,8 +208,8 @@ internal_cmd_frequencies (void)
   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))
@@ -246,7 +246,6 @@ internal_cmd_frequencies (void)
     cmd.sort = FRQ_AVALUE;
 
   /* Do it! */
-  update_weighting (&default_dict);
   procedure (precalc, calc, postcalc);
 
   return CMD_SUCCESS;
@@ -361,10 +360,7 @@ calc (struct ccase *c)
   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++)
     {
@@ -596,10 +592,11 @@ frq_custom_variables (struct cmd_frequencies *cmd unused)
   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;
 
@@ -635,14 +632,14 @@ frq_custom_variables (struct cmd_frequencies *cmd unused)
     {
       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;
 
@@ -675,7 +672,8 @@ static int
 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;
@@ -688,7 +686,8 @@ frq_custom_grouped (struct cmd_frequencies *cmd unused)
        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 ('('))
          {
@@ -719,7 +718,7 @@ frq_custom_grouped (struct cmd_frequencies *cmd unused)
 
        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)
@@ -734,7 +733,8 @@ frq_custom_grouped (struct cmd_frequencies *cmd unused)
        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;
index 8aecc386e9130df42ce109a49b87817db4b54529..ba95ade48a8a0b0da3052438550d629abfa00047 100644 (file)
--- a/src/get.c
+++ b/src/get.c
@@ -44,7 +44,7 @@ struct save_trns
     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. */
   };
 
@@ -77,9 +77,6 @@ cmd_get (void)
   struct dictionary *dict;
   int options = GTSV_OPT_NONE;
 
-  int i;
-  int nval;
-
   lex_match_id ("GET");
   discard_variables ();
 
@@ -107,18 +104,7 @@ cmd_get (void)
   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"));
@@ -131,7 +117,8 @@ cmd_get (void)
     }
 #endif
 
-  restore_dictionary (dict);
+  dict_destroy (default_dict);
+  default_dict = dict;
 
   vfm_source = &get_source;
   get_file = handle;
@@ -139,12 +126,10 @@ cmd_get (void)
   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;
@@ -165,12 +150,12 @@ cmd_save_internal (int x)
   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);
@@ -187,7 +172,7 @@ cmd_save_internal (int x)
   inf.compress = !!(options & GTSV_OPT_COMPRESSED);
   if (!sfm_write_dictionary (&inf))
     {
-      free_dictionary (dict);
+      dict_destroy (dict);
       fh_close_handle (handle);
       return CMD_FAILURE;
     }
@@ -197,22 +182,22 @@ cmd_save_internal (int x)
   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;
 }
@@ -234,7 +219,7 @@ cmd_xsave (void)
 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;
 }
 
@@ -246,7 +231,7 @@ save_trns_proc (struct trns_header * t unused, struct ccase * c)
 
   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;
@@ -279,27 +264,6 @@ save_trns_free (struct trns_header *pt)
   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
@@ -308,6 +272,8 @@ static int rename_variables (struct dictionary * dict);
    *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)
 {
@@ -316,24 +282,18 @@ 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 ('/'))
@@ -346,68 +306,32 @@ trim_dictionary (struct dictionary *dict, int *options)
        {
          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"))
        {
@@ -420,7 +344,7 @@ trim_dictionary (struct dictionary *dict, int *options)
          return 0;
        }
 
-      if (dict->nvar == 0)
+      if (dict_get_var_cnt (dict) == 0)
        {
          msg (SE, _("All variables deleted from system file dictionary."));
          return 0;
@@ -450,6 +374,7 @@ rename_variables (struct dictionary * dict)
   struct variable **v;
   char **new_names;
   int nv, nn;
+  char *err_name;
 
   int group;
 
@@ -466,7 +391,7 @@ rename_variables (struct dictionary * dict)
        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 "
@@ -476,7 +401,7 @@ rename_variables (struct dictionary * dict)
          return 0;
        }
       
-      rename_variable (dict, v, tokid);
+      dict_rename_var (dict, v, tokid);
       lex_get ();
       return 1;
     }
@@ -490,43 +415,35 @@ rename_variables (struct dictionary * dict)
       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);
@@ -562,7 +479,7 @@ get_source_destroy_source (void)
 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 ();
@@ -607,7 +524,7 @@ struct mtf_file
     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. */
@@ -617,6 +534,13 @@ static int mtf_n_by;
 /* 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);
@@ -642,8 +566,10 @@ cmd_match_files (void)
   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
     {
@@ -748,7 +674,7 @@ cmd_match_files (void)
                goto lossage;
            }
          else
-           file->dict = &default_dict;
+           file->dict = default_dict;
          if (!mtf_merge_dictionary (file))
            goto lossage;
        }
@@ -801,7 +727,7 @@ cmd_match_files (void)
          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."),
@@ -859,7 +785,7 @@ cmd_match_files (void)
 
          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."),
@@ -911,10 +837,12 @@ cmd_match_files (void)
      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 ();
@@ -923,6 +851,11 @@ cmd_match_files (void)
   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;
@@ -983,8 +916,8 @@ static void
 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);
@@ -1006,7 +939,8 @@ mtf_free (void)
   
   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
@@ -1029,9 +963,9 @@ mtf_delete_file_in_place (struct mtf_file **file)
   {
     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;
@@ -1055,7 +989,8 @@ mtf_read_nonactive_records (void)
       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);
@@ -1109,10 +1044,6 @@ mtf_compare_BY_values (struct mtf_file *a, struct mtf_file *b)
   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)
@@ -1219,7 +1150,7 @@ 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)
@@ -1228,13 +1159,13 @@ mtf_processing (struct ccase *c unused)
        {
          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",
@@ -1261,13 +1192,13 @@ mtf_processing (struct ccase *c unused)
        {
          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",
@@ -1322,31 +1253,41 @@ mtf_merge_dictionary (struct mtf_file *f)
 {
   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)
@@ -1354,19 +1295,17 @@ mtf_merge_dictionary (struct mtf_file *f)
            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 "
@@ -1394,9 +1333,6 @@ cmd_import (void)
   int options = GTSV_OPT_NONE;
   int type;
 
-  int i;
-  int nval;
-
   lex_match_id ("IMPORT");
 
   for (;;)
@@ -1451,18 +1387,7 @@ cmd_import (void)
   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"));
@@ -1475,7 +1400,8 @@ cmd_import (void)
     }
 #endif
 
-  restore_dictionary (dict);
+  dict_destroy (default_dict);
+  default_dict = dict;
 
   vfm_source = &import_source;
   get_file = handle;
@@ -1488,7 +1414,7 @@ cmd_import (void)
 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 ();
@@ -1530,12 +1456,12 @@ cmd_export (void)
   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);
@@ -1549,7 +1475,7 @@ cmd_export (void)
   /* Write dictionary. */
   if (!pfm_write_dictionary (handle, dict))
     {
-      free_dictionary (dict);
+      dict_destroy (dict);
       fh_close_handle (handle);
       return CMD_FAILURE;
     }
@@ -1559,15 +1485,15 @@ cmd_export (void)
   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;
 }
@@ -1580,7 +1506,7 @@ export_write_case_func (struct ccase *c)
 
   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];
@@ -1588,9 +1514,6 @@ export_write_case_func (struct ccase *c)
        (*p++).c = c->data[v->fv].s;
     }
 
-  printf (".");
-  fflush (stdout);
-  
   pfm_write_case (trns->f, (union value *) trns->case_buf);
   return 1;
 }
index 5b8588c88d9d6aa5c06389152921743bc4f43513..e5dae5d9ce91552d0e5b20010173c8bdd6421973 100644 (file)
@@ -18,6 +18,7 @@
    02111-1307, USA. */
 
 #include <config.h>
+#include "getline.h"
 #include <assert.h>
 #include <stdio.h>
 #include <errno.h>
@@ -25,8 +26,8 @@
 #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"
@@ -225,7 +226,7 @@ getl_add_DO_REPEAT_file (struct getl_script *file)
 }
 
 /* Display a welcoming message. */
-void
+static void
 welcome (void)
 {
   getl_welcomed = 1;
index d879546c68d966f6fe811deb978506116385d9cb..daa4f97af1ce5d19fcd8452d6fc7bab03349adb4 100644 (file)
@@ -18,7 +18,7 @@
    02111-1307, USA. */
 
 #include <config.h>
-
+#include "glob.h"
 #include <assert.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -82,6 +82,7 @@ extern void stifle_history ();
 #include "do-ifP.h"
 #include "error.h"
 #include "expr.h"
+#include "file-handle.h"
 #include "filename.h"
 #include "getline.h"
 #include "hash.h"
@@ -96,7 +97,7 @@ extern void stifle_history ();
 #include "vfm.h"
 
 /* var.h */
-struct dictionary default_dict;
+struct dictionary *default_dict;
 struct expression *process_if_expr;
 
 struct ccase *temp_case;
@@ -166,8 +167,7 @@ init_glob (int argc unused, char **argv)
 #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);
@@ -306,11 +306,7 @@ init_glob (int argc unused, char **argv)
   logfile = NULL;
 
   /* file-handle.h */
-  {
-    extern void fh_init_files (void);
-    
-    fh_init_files ();
-  }
+  fh_init_files ();
   
   get_date ();
 }
diff --git a/src/glob.h b/src/glob.h
new file mode 100644 (file)
index 0000000..0b15f34
--- /dev/null
@@ -0,0 +1,25 @@
+/* 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 */
index 12572cf4297000c13151aedcab0ee12818efc724..b1c7f763aabc1c08c8df4ab6fb31968879f412f9 100644 (file)
@@ -18,6 +18,7 @@
    02111-1307, USA. */
 
 #include <config.h>
+#include "font.h"
 #include <assert.h>
 #include <stdio.h>
 #include <errno.h>
@@ -27,7 +28,6 @@
 #include "alloc.h"
 #include "error.h"
 #include "filename.h"
-#include "font.h"
 #include "hash.h"
 #include "pool.h"
 #include "str.h"
index f6bad64b8889dbc2b3bf860924f8fc21d470489a..38dd7ee27671f0eae0764bf6864b388e43ef2da6 100644 (file)
    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"
 
@@ -76,43 +76,39 @@ next_power_of_2 (size_t x)
     }
 }
 
-/* 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;
 }
 
@@ -259,7 +255,7 @@ hsh_data (struct hsh_table *h)
 
 /* 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_;
index a90aefda81826dd7962026dacce945edc2370fc1..c321327a63f4c4b4d9b94a4d77a046b5b8ca7005 100644 (file)
    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
index 7644356b73155fa5c702b5a572c76fa72edc0dd6..f2dc8697c0ee676a0067053a8c93a5ca60654793 100644 (file)
@@ -23,6 +23,8 @@
 /* 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
   {
index 42d818b519f908004e0eb876cdfc089ffd53a67b..3f7416290b070d92c94db48c8f8dbf7688fa03b8 100644 (file)
@@ -21,6 +21,7 @@
 #if !NO_HTML
 
 #include <config.h>
+#include "htmlP.h"
 #include <assert.h>
 #include <errno.h>
 #include <stdlib.h>
@@ -35,7 +36,6 @@
 #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;
@@ -87,7 +87,7 @@ html_preopen_driver (struct outp_driver *this)
   return 1;
 }
 
-int
+static int
 html_postopen_driver (struct outp_driver *this)
 {
   struct html_driver_ext *x = this->ext;
@@ -105,7 +105,7 @@ html_postopen_driver (struct outp_driver *this)
   return 1;
 }
 
-int
+static int
 html_close_driver (struct outp_driver *this)
 {
   struct html_driver_ext *x = this->ext;
@@ -141,7 +141,7 @@ static struct outp_option option_tab[] =
 };
 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;
@@ -358,7 +358,7 @@ preclose (struct file_ext *f)
   return 1;
 }
 
-int
+static int
 html_open_page (struct outp_driver *this)
 {
   struct html_driver_ext *x = this->ext;
@@ -378,7 +378,7 @@ html_open_page (struct outp_driver *this)
   return !ferror (x->file.file);
 }
 
-int
+static int
 html_close_page (struct outp_driver *this)
 {
   struct html_driver_ext *x = this->ext;
@@ -390,7 +390,7 @@ html_close_page (struct outp_driver *this)
 
 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;
index 2b3f7bf8cf308772eb07a91ca2ff19101dd0bb0e..6fba390d29a699faf6ce29020d713bddad4ac060 100644 (file)
@@ -27,7 +27,6 @@
 #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);
@@ -61,15 +66,14 @@ cmd_input_program (void)
 
   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");
@@ -80,7 +84,7 @@ cmd_end_input_program (void)
       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."));
 
@@ -88,9 +92,25 @@ cmd_end_input_program (void)
      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 ();
 }
@@ -99,110 +119,55 @@ cmd_end_input_program (void)
 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;
diff --git a/src/inpt-pgm.h b/src/inpt-pgm.h
deleted file mode 100644 (file)
index c46fe7a..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/* 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 */
index 6bcb46eb97c88c71028f435f1dcd65fad254e320..edcc5a2ae381498d901ae1589c4daf6292715d2f 100644 (file)
@@ -18,6 +18,7 @@
    02111-1307, USA. */
 
 #include <config.h>
+#include "lexer.h"
 #include <assert.h>
 #include <ctype.h>
 #include <errno.h>
@@ -29,7 +30,6 @@
 #include "command.h"
 #include "error.h"
 #include "getline.h"
-#include "lexer.h"
 #include "magic.h"
 #include "settings.h"
 #include "str.h"
index 174c7ead573ad9f30900bb4b9d4851b565ec8aea..824e51da27d1fdbefc977ab691b41f5d3cb4dd5d 100644 (file)
@@ -152,8 +152,8 @@ cmd_list (void)
   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."));
@@ -192,13 +192,12 @@ cmd_list (void)
   /* 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)
            {
@@ -208,7 +207,7 @@ cmd_list (void)
                                          (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
index 1ccd1a5631f69faab42ba0452c1d17f0565e27b4..c8715bcad149ca1539f678648c951ea7df8e0426 100644 (file)
@@ -192,7 +192,7 @@ internal_cmd_loop (void)
   /* 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;
 
@@ -252,10 +252,10 @@ internal_cmd_loop (void)
   /* 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
index 3f519e5e0f6974ab477b1d01c268a111a0083660..e0cd4f3e4fac1678d37483628f6e3c778ce7de01 100644 (file)
    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"
 
@@ -51,9 +54,6 @@ int start_interactive;
 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);
index 986186ab9c0f54264ad3b34b609d66332b1f3a8f..c462b7cf16e93d58d14c2c773942c95ff3569715 100644 (file)
@@ -233,8 +233,8 @@ cmd_matrix_data (void)
                
                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;
                  }
@@ -246,8 +246,8 @@ cmd_matrix_data (void)
          }
          
          {
-           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;
          }
@@ -303,7 +303,7 @@ cmd_matrix_data (void)
              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_"))
@@ -313,44 +313,41 @@ cmd_matrix_data (void)
                  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"))
@@ -364,7 +361,7 @@ cmd_matrix_data (void)
            }
          seen |= 4;
 
-         if (!parse_variables (NULL, &factors, &n_factors, PV_NONE))
+         if (!parse_variables (default_dict, &factors, &n_factors, PV_NONE))
            goto lossage;
          
          {
@@ -560,8 +557,8 @@ cmd_matrix_data (void)
       
   /* 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;
   }
@@ -569,13 +566,13 @@ cmd_matrix_data (void)
   /* 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. */
@@ -592,9 +589,9 @@ cmd_matrix_data (void)
     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);
@@ -731,13 +728,13 @@ debug_print (void)
   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");
@@ -1060,7 +1057,8 @@ read_matrices_without_rowtype (void)
     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;
 
@@ -1210,7 +1208,7 @@ nr_read_data_lines (int per_factor, int cell, int content, int compare)
            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;
              }
 
@@ -1318,7 +1316,7 @@ matrix_data_read_without_rowtype (void)
 
       nr_output_data ();
 
-      if (default_dict.n_splits == 0 || !another_token ())
+      if (dict_get_split_cnt (default_dict) == 0 || !another_token ())
        return 1;
     }
 }
@@ -1330,6 +1328,8 @@ static int
 nr_read_splits (int compare)
 {
   static int just_read = 0;
+  size_t split_cnt;
+  size_t i;
 
   if (compare && just_read)
     {
@@ -1337,43 +1337,41 @@ nr_read_splits (int compare)
       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;
 }
@@ -1452,18 +1450,15 @@ dump_cell_content (int content, double *cp)
 
        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 ();
       }
   }
@@ -1474,10 +1469,13 @@ static void
 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)
@@ -1601,8 +1599,10 @@ static int
 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)
@@ -1610,14 +1610,15 @@ wr_read_splits (void)
   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;
@@ -1683,10 +1684,13 @@ static int
 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. */
@@ -2003,7 +2007,8 @@ wr_read_indeps (void)
        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;
          }
 
index 7e474677aa92dc0bc7a93cb1b96e29912130e223..30e3fde231860fadb0a7055255345bccae42abf9 100644 (file)
    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,
index bda3eb8568ac1bd55fb3b8b9f2881f8a65d9604b..a8921b38bf89e0a7db43365748c671227e2af2e6 100644 (file)
@@ -127,23 +127,14 @@ free:
   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 ('=');
@@ -155,31 +146,20 @@ mns_custom_tables (struct cmd_means *cmd)
       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));
@@ -202,7 +182,7 @@ mns_custom_tables (struct cmd_means *cmd)
                             "CROSSBREAK, but not specified on "
                             "VARIABLES."),
                       v_dim[0][i]->name);
-                 return 0;
+                  goto lossage;
                }
              
              if (n_dim == 1)
@@ -215,7 +195,7 @@ mns_custom_tables (struct cmd_means *cmd)
                      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)
@@ -224,7 +204,7 @@ mns_custom_tables (struct cmd_means *cmd)
                                 "have noninteger endpoints in their "
                                 "ranges."),
                           v_dim[0][i]->name);
-                     return 0;
+                      goto lossage;
                    }
                }
            }
@@ -232,26 +212,12 @@ mns_custom_tables (struct cmd_means *cmd)
     }
   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. */
@@ -275,8 +241,8 @@ mns_custom_variables (struct cmd_means *cmd)
     {
       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
@@ -285,7 +251,7 @@ mns_custom_variables (struct cmd_means *cmd)
       
       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;
 
index 23d803fcf05e884ed33286d534625eb22caf9718..1e07fcfd54b2deffff98f5d66eaf0aa9c708c544 100644 (file)
@@ -104,7 +104,7 @@ parse_varnames (void)
 {
   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 ('('))
     {
index 2ef156a0387d93764565a12fbdee734dced62bb7..ac7d446dcd4e8b363b72041439f93569975fc5ac 100644 (file)
@@ -58,28 +58,31 @@ struct ordering
     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
@@ -92,14 +95,21 @@ cmd_modify_vars (void)
   /* 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 ('/');
@@ -113,7 +123,7 @@ cmd_modify_vars (void)
          if (already_encountered & 1)
            {
              msg (SE, _("REORDER subcommand may be given at most once."));
-             goto lossage;
+             goto done;
            }
          already_encountered |= 1;
 
@@ -137,9 +147,9 @@ cmd_modify_vars (void)
                    {
                      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
                {
@@ -147,20 +157,20 @@ cmd_modify_vars (void)
                    {
                      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,
@@ -168,148 +178,131 @@ cmd_modify_vars (void)
            }
          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
        {
@@ -317,7 +310,7 @@ cmd_modify_vars (void)
            msg (SE, _("Unrecognized subcommand name `%s'."), tokid);
          else
            msg (SE, _("Subcommand name expected."));
-         goto lossage;
+         goto done;
        }
 
       if (token == '.')
@@ -325,43 +318,30 @@ cmd_modify_vars (void)
       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
@@ -386,160 +366,166 @@ compare_variables_given_ordering (const void *a_, const void *b_,
   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;
 }
index 065b1a30294488df4d1b912c68c3398d75938914..1619a99af342236c7ccc78b0fb7e8adaaf794d3d 100644 (file)
@@ -73,8 +73,7 @@ cmd_numeric (void)
       /* 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
@@ -156,8 +155,8 @@ cmd_string (void)
       /* 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
@@ -195,7 +194,7 @@ cmd_leave (void)
   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++)
     {
index 370ad5910cf6b2241d13bc8d1b2aa38592863c5f..f3e0da7ea392f28a7bec0cdb3b0cc5d3d0b87c76 100644 (file)
@@ -18,6 +18,7 @@
    02111-1307, USA. */
 
 #include <config.h>
+#include "output.h"
 #include <assert.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -29,7 +30,6 @@
 #include "filename.h"
 #include "lexer.h"
 #include "misc.h"
-#include "output.h"
 #include "settings.h"
 #include "str.h"
 
@@ -194,7 +194,7 @@ expand_name (char *bp, char *ep)
 
 /* 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];
@@ -423,7 +423,7 @@ outp_configure_macro (char *bp)
 
 /* 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;
index 514e7bda6bbee7905d65c42029f618bb8bab54cf..99a7931ae6129679aa02cd0e08ec9c3d87010d33 100644 (file)
@@ -35,6 +35,7 @@ char *alloca ();
 #endif
 #endif
 
+#include "pfm.h"
 #include <assert.h>
 #include <stdarg.h>
 #include <stdio.h>
@@ -49,7 +50,6 @@ char *alloca ();
 #include "hash.h"
 #include "magic.h"
 #include "misc.h"
-#include "pfm.h"
 #include "str.h"
 #include "value-labels.h"
 #include "var.h"
@@ -298,7 +298,7 @@ pfm_read_dictionary (struct file_handle *h, struct pfm_read_info *inf)
   
   fclose (ext->file);
   if (ext && ext->dict)
-    free_dictionary (ext->dict);
+    dict_destroy (ext->dict);
   free (ext);
   h->class = NULL;
   h->ext = NULL;
@@ -421,7 +421,7 @@ read_float (struct file_handle *h)
 }
   
 /* 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);
@@ -683,6 +683,7 @@ static int
 read_variables (struct file_handle *h)
 {
   struct pfm_fhuser_ext *ext = h->ext;
+  char *weight_name = NULL;
   int i;
   
   if (!match (68 /* 4 */))
@@ -703,16 +704,21 @@ read_variables (struct file_handle *h)
       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++)
@@ -787,7 +793,7 @@ read_variables (struct file_handle *h)
       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));
@@ -852,16 +858,22 @@ read_variables (struct file_handle *h)
          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;
 }
 
@@ -922,7 +934,7 @@ read_value_label (struct file_handle *h)
        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));
 
@@ -1016,9 +1028,9 @@ pfm_read_case (struct file_handle *h, union value *perm, struct dictionary *dict
 
   /* 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;
index e2bf68f595bb48cdb457e748d2e89cbe6781259e..cf815e4f8064b1766408b3d7bcadfb524804f713 100644 (file)
@@ -18,6 +18,7 @@
    02111-1307, USA. */
 
 #include <config.h>
+#include "pfm.h"
 #include <assert.h>
 #include <ctype.h>
 #include <errno.h>
@@ -32,7 +33,6 @@
 #include "gmp.h"
 #include "hash.h"
 #include "magic.h"
-#include "pfm.h"
 #include "str.h"
 #include "value-labels.h"
 #include "var.h"
@@ -94,10 +94,10 @@ pfm_write_dictionary (struct file_handle *handle, struct dictionary *dict)
   {
     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. */
@@ -385,11 +385,11 @@ write_variables (struct file_handle *h, struct dictionary *dict)
 {
   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] =
        {
@@ -399,7 +399,7 @@ write_variables (struct file_handle *h, struct dictionary *dict)
       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)
@@ -424,10 +424,10 @@ write_value_labels (struct file_handle *h, struct dictionary *dict)
 {
   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))
index ebf4401e67873239c93007389a8240581e4d8072..ad506ac34fce18e7db3aa8b8bc096085b1fc159d 100644 (file)
--- a/src/pfm.h
+++ b/src/pfm.h
@@ -48,7 +48,8 @@ union value;
 
 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);
index 0f5663d1f064c5b6813d86dd3644c2bdf687c51a..c30b2f7bc370cb0d7aa03ab4683cc450804cf484 100644 (file)
 #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. */
index 919048200b99ec0895fb864f5da2ddc3ec4d6eb6..ef6cebe9ae0594c955f4408dd83d7e726eafa01e 100644 (file)
@@ -302,7 +302,7 @@ static char *quote_ps_string (char *dest, const char *string);
 \f
 /* Driver initialization. */
 
-int
+static int
 ps_open_global (struct outp_class *this unused)
 {
   init_fonts ();
@@ -310,13 +310,13 @@ ps_open_global (struct outp_class *this unused)
   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. */
@@ -328,7 +328,7 @@ ps_font_sizes (struct outp_class *this unused, int *n_valid_sizes)
   return valid_sizes;
 }
 
-int
+static int
 ps_preopen_driver (struct outp_driver *this)
 {
   struct ps_driver_ext *x;
@@ -403,7 +403,7 @@ ps_preopen_driver (struct outp_driver *this)
   return 1;
 }
 
-int
+static int
 ps_postopen_driver (struct outp_driver *this)
 {
   struct ps_driver_ext *x = this->ext;
@@ -476,7 +476,7 @@ ps_postopen_driver (struct outp_driver *this)
   return 1;
 }
 
-int
+static int
 ps_close_driver (struct outp_driver *this)
 {
   struct ps_driver_ext *x = this->ext;
@@ -578,7 +578,7 @@ static struct outp_option option_tab[] =
 };
 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;
@@ -1652,7 +1652,7 @@ preclose (struct file_ext *f)
   return 1;
 }
 
-int
+static int
 ps_open_page (struct outp_driver *this)
 {
   struct ps_driver_ext *x = this->ext;
@@ -1709,7 +1709,7 @@ ps_open_page (struct outp_driver *this)
   return !ferror (x->file.file);
 }
 
-int
+static int
 ps_close_page (struct outp_driver *this)
 {
   struct ps_driver_ext *x = this->ext;
@@ -1912,7 +1912,7 @@ line (struct outp_driver *this, int type, int ind, int dep1, int dep2)
   (*f)->ndep++;
 }
 
-void
+static void
 ps_line_horz (struct outp_driver *this, const struct rect *r,
              const struct color *c unused, int style)
 {
@@ -1929,7 +1929,7 @@ ps_line_horz (struct outp_driver *this, const struct rect *r,
     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)
 {
@@ -1951,7 +1951,7 @@ ps_line_vert (struct outp_driver *this, const struct rect *r,
 #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)
@@ -2033,38 +2033,25 @@ ps_line_intersection (struct outp_driver *this, const struct rect *r,
     }
 }
 
-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);
@@ -2161,7 +2148,7 @@ draw_headers (struct outp_driver *this)
 \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;
@@ -2190,7 +2177,7 @@ ps_text_set_font_by_name (struct outp_driver *this, const char *dit)
   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;
@@ -2237,7 +2224,7 @@ ps_text_set_font_by_position (struct outp_driver *this, int pos)
   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;
@@ -2248,7 +2235,7 @@ ps_text_set_font_family (struct outp_driver *this, const char *s)
   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;
@@ -2257,7 +2244,7 @@ ps_text_get_font_name (struct outp_driver *this)
   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;
@@ -2266,7 +2253,7 @@ ps_text_get_font_family (struct outp_driver *this)
   return x->family;
 }
 
-int
+static int
 ps_text_set_size (struct outp_driver *this, int size)
 {
   struct ps_driver_ext *x = this->ext;
@@ -2276,7 +2263,7 @@ ps_text_set_size (struct outp_driver *this, int size)
   return 1;
 }
 
-int
+static int
 ps_text_get_size (struct outp_driver *this, int *em_width)
 {
   struct ps_driver_ext *x = this->ext;
@@ -2788,14 +2775,14 @@ exit:
   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);
index 3f556707cdbb40a8619363db6f8903230de37d8b..b0ef286debc2680d2b7e3876fe0fcd74f6ee8450 100644 (file)
@@ -453,7 +453,7 @@ fail:
 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)
index 953289c093d2c1a36d48e544056c5a8e13f59cc8..197fd8d9ca00a843f9b9dee7306496c9c58832a2 100644 (file)
--- a/src/q2c.c
+++ b/src/q2c.c
@@ -87,7 +87,7 @@ char *tokstr;
 char nullstr[] = "";
 
 /* Close all open files and delete the output file, on failure. */
-void
+static void
 finish_up (void)
 {
   if (!is_open)
@@ -151,7 +151,7 @@ error (const char *format,...)
 
 /* Allocate a block of SIZE bytes and return a pointer to its
    beginning. */
-void *
+static void *
 xmalloc (size_t size)
 {
   void *vp;
@@ -166,34 +166,9 @@ xmalloc (size_t size)
   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;
@@ -212,7 +187,7 @@ xstrdup (const char *s)
 
 /* 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];
@@ -226,7 +201,7 @@ get_buffer (void)
    
 /* 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;
@@ -241,7 +216,7 @@ st_lower (const char *s)
 
 /* 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;
@@ -256,7 +231,7 @@ st_upper (const char *s)
 
 /* 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))
@@ -266,7 +241,7 @@ skip_ws (const 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++;
@@ -306,7 +281,7 @@ symbol *symtab;
    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;
@@ -352,7 +327,7 @@ add_symbol (const char *name, int unique, int value)
 
 /* 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;
@@ -388,7 +363,7 @@ dump_token (void)
 #endif /* DEBUGGING */
 
 /* Reads a token from the input file. */
-int
+static int
 lex_get (void)
 {
   /* Skip whitespace and check for end of file. */
@@ -443,7 +418,7 @@ lex_get (void)
 }
 
 /* Force the current token to be an identifier token. */
-void
+static void
 force_id (void)
 {
   if (token != T_ID)
@@ -451,7 +426,7 @@ force_id (void)
 }
 
 /* Force the current token to be a string token. */
-void
+static void
 force_string (void)
 {
   if (token != T_STRING)
@@ -460,7 +435,7 @@ force_string (void)
 
 /* 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))
@@ -473,7 +448,7 @@ match_id (const char *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)
@@ -485,7 +460,7 @@ match_token (int t)
 }
 
 /* Force the current token to be T, and skip it. */
-void
+static void
 skip_token (int t)
 {
   if (token != t)
@@ -594,7 +569,7 @@ subcommand *def;
 void parse_subcommands (void);
 
 /* Parse an entire specification. */
-void
+static void
 parse (void)
 {
   /* Get the command name and prefix. */
@@ -617,7 +592,7 @@ parse (void)
 
 /* 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;
@@ -688,7 +663,7 @@ parse_setting (setting *s, specifier *spec)
 
 /* Parse a single specifier into SPEC, given subcommand information
    SBC. */
-void
+static void
 parse_specifier (specifier *spec, subcommand *sbc)
 {
   spec->index = 0;
@@ -737,7 +712,7 @@ parse_specifier (specifier *spec, subcommand *sbc)
 }
 
 /* Parse a list of specifiers for subcommand SBC. */
-void
+static void
 parse_specifiers (subcommand *sbc)
 {
   specifier **spec = &sbc->spec;
@@ -761,7 +736,7 @@ parse_specifiers (subcommand *sbc)
 }
 
 /* Parse a subcommand into SBC. */
-void
+static void
 parse_subcommand (subcommand *sbc)
 {
   if (match_token ('*'))
@@ -916,7 +891,7 @@ dump (int indention, const char *format, ...)
 
 /* 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)
@@ -941,7 +916,7 @@ dump_specifier_vars (const specifier *spec, const subcommand *sbc)
 }
 
 /* Returns 1 if string T is a PSPP keyword, 0 otherwise. */
-int
+static int
 is_keyword (const char *t)
 {
   static const char *kw[] =
@@ -960,7 +935,7 @@ is_keyword (const char *t)
 /* 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 ();
@@ -977,7 +952,7 @@ make_identifier (const char *name)
 }
 
 /* Writes the struct and enum declarations for the parser. */
-void
+static void
 dump_declarations (void)
 {
   indent = 0;
@@ -1167,7 +1142,7 @@ dump_declarations (void)
 
 /* 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)
@@ -1201,7 +1176,7 @@ dump_specifier_init (const specifier *spec, const subcommand *sbc)
 }
 
 /* Write code to initialize all variables. */
-void
+static void
 dump_vars_init (void)
 {
   /* Loop through all the subcommands. */
@@ -1274,7 +1249,7 @@ dump_vars_init (void)
 
 /* 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;
@@ -1302,7 +1277,7 @@ make_match (const char *t)
 
 /* 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;
@@ -1446,7 +1421,7 @@ dump_specifier_parse (const specifier *spec, const subcommand *sbc)
 }
 
 /* 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)
@@ -1517,7 +1492,7 @@ dump_subcommand (const subcommand *sbc)
     }
   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),
@@ -1599,7 +1574,7 @@ dump_subcommand (const subcommand *sbc)
 }
 
 /* Write out entire parser. */
-void
+static void
 dump_parser (void)
 {
   int f;
@@ -1620,17 +1595,19 @@ dump_parser (void)
   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));
@@ -1709,7 +1686,7 @@ dump_parser (void)
 }
 
 /* Write the output file header. */
-void
+static void
 dump_header (void)
 {
   time_t curtime;
@@ -1730,7 +1707,7 @@ dump_header (void)
 }
 
 /* Write out commands to free variable state. */
-void
+static void
 dump_free (void)
 {
   subcommand *sbc;
@@ -1757,7 +1734,7 @@ dump_free (void)
 
 /* 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];
index d62c1a3dede81e2a64e789c1cebedc604c25871f..ab78b32bb256f19c121c2de34a43529cdb9684d9 100644 (file)
@@ -18,6 +18,7 @@
    02111-1307, USA. */
 
 #include <config.h>
+#include "random.h"
 #include <assert.h>
 #include <inttypes.h>
 #include <limits.h>
@@ -26,7 +27,6 @@
 #include <time.h>
 #include "alloc.h"
 #include "magic.h"
-#include "random.h"
 #include "settings.h"
 
 /* Random number generator. */
@@ -48,15 +48,15 @@ rng_create (void)
   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
@@ -66,7 +66,7 @@ rng_destroy (struct rng *rng)
 }
 
 /* Swap bytes. */
-static inline void
+static void
 swap_byte (uint8_t *a, uint8_t *b) 
 {
   uint8_t t = *a;
@@ -80,7 +80,7 @@ void
 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;
 
@@ -90,7 +90,7 @@ rng_seed (struct rng *rng, const void *key_, size_t size)
   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);
index 91dec4ffea7f32ec549a0ce63e83188df3b702ba..21aef7c96191cdac332a8a3aec0d4ded141de3f5 100644 (file)
@@ -20,6 +20,8 @@
 #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);
index 146e8a36a5b28e102558638a16b85bd18cd9cf8b..2485b3d1ee9c11b5ce9b4caff34c848bb456ba24 100644 (file)
@@ -165,7 +165,7 @@ cmd_recode (void)
       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
@@ -295,7 +295,7 @@ cmd_recode (void)
          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)
                  {
@@ -321,7 +321,7 @@ cmd_recode (void)
          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)
                  {
@@ -413,13 +413,12 @@ cmd_recode (void)
   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
@@ -929,7 +928,7 @@ debug_print (struct rcd_var * head)
    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;
index 6821314c91546c034b01ae6c87d2d8e4d8d6ca9b..212d7bdfb78c8a3fe3d9dd13a6ccbe320edb3b8d 100644 (file)
 #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;
 
@@ -51,15 +47,15 @@ cmd_rename_variables (void)
 
   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 ('='))
@@ -67,17 +63,17 @@ cmd_rename_variables (void)
          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 (')'))
@@ -88,67 +84,23 @@ cmd_rename_variables (void)
     }
   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;
 }
index aef5e9842db1679c8ecee195e0ce9ccc85b67b4c..09809fde1e5414d9043158cf898e2ff50d349203 100644 (file)
@@ -18,6 +18,7 @@
    02111-1307, USA. */
 
 #include <config.h>
+#include "repeat.h"
 #include <assert.h>
 #include <ctype.h>
 #include <math.h>
@@ -328,9 +329,9 @@ internal_cmd_do_repeat (void)
            {
              /* 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. */
@@ -513,7 +514,7 @@ cmd_end_repeat (void)
 \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;
diff --git a/src/repeat.h b/src/repeat.h
new file mode 100644 (file)
index 0000000..33b8e75
--- /dev/null
@@ -0,0 +1,25 @@
+/* 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 */
index f4afd9c65cbffe3cda2ae2c50db033a3c0d0464a..07fe318f114b578991aee80a73235f46d5fee1f7 100644 (file)
@@ -87,7 +87,7 @@ cmd_filter (void)
   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;
@@ -108,8 +108,8 @@ cmd_filter (void)
          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;
     }
index 8683bff7ea7ef500061ce3ccb0862c78cd3a8f68..bfd437c6c9c884107e67e6e1fbb7ec4a494f1284 100644 (file)
--- a/src/set.q
+++ b/src/set.q
@@ -59,6 +59,7 @@
 */     
    
 #include <config.h>
+#include "settings.h"
 #include <assert.h>
 #include <stdio.h>
 #include <errno.h>
@@ -72,7 +73,6 @@
 #include "output.h"
 #include "var.h"
 #include "format.h"
-#include "settings.h"
 
 double set_blanks;
 int set_compression;
@@ -865,16 +865,6 @@ stc_custom_workdev (struct cmd_set *cmd unused)
   return 0;
 }
 
-\f
-/* GSET. */
-
-int
-cmd_gset (void)
-{
-  /* FIXME */
-  return CMD_FAILURE;
-}
-
 /*
    Local Variables:
    mode: c
index d9d6f41fb26be464e8a9e0788288d6aea07c3607..b8ba86d47672001204aec95375d19e42a1249432 100644 (file)
@@ -35,6 +35,8 @@ char *alloca ();
 #endif
 #endif
 
+#include "sfm.h"
+#include "sfmP.h"
 #include <assert.h>
 #include <stdlib.h>
 #include <ctype.h>
@@ -49,8 +51,6 @@ char *alloca ();
 #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"
@@ -306,10 +306,10 @@ sfm_read_dictionary (struct file_handle * h, struct sfm_read_info * inf)
        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 (;;)
@@ -428,7 +428,7 @@ lossage:
   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;
@@ -544,20 +544,7 @@ read_header (struct file_handle * h, struct sfm_read_info * inf)
   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);
@@ -647,14 +634,15 @@ read_header (struct file_handle * h, struct sfm_read_info * inf)
   {
     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;
        }
   }
@@ -692,14 +680,9 @@ lossage:
 }
 
 /* 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)
 {
@@ -713,7 +696,6 @@ 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
@@ -721,6 +703,7 @@ read_variables (struct file_handle * h, struct variable *** var_by_index)
   for (i = 0; i < ext->case_size; i++)
     {
       struct variable *vv;
+      char name[9];
       int j;
 
       assertive_bufread (h, &sv, sizeof sv, 0);
@@ -768,12 +751,6 @@ read_variables (struct file_handle * h, struct variable *** var_by_index)
        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] != '#')
@@ -786,7 +763,7 @@ read_variables (struct file_handle * h, struct variable *** var_by_index)
        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++)
@@ -799,39 +776,31 @@ read_variables (struct file_handle * h, struct variable *** var_by_index)
            {
              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)
@@ -928,29 +897,11 @@ read_variables (struct file_handle * h, struct variable *** var_by_index)
   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;
@@ -1064,10 +1015,10 @@ read_value_labels (struct file_handle * h, struct variable ** var_by_index)
   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);
@@ -1153,6 +1104,7 @@ read_value_labels (struct file_handle * h, struct variable ** var_by_index)
 
   for (i = 0; i < n_labels; i++)
     free (labels[i].label);
+  free (labels);
   free (var);
   return 1;
 
@@ -1198,20 +1150,24 @@ read_documents (struct file_handle * h)
   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:
@@ -1234,12 +1190,10 @@ dump_dictionary (struct dictionary * dict)
       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)
@@ -1441,10 +1395,6 @@ sfm_read_case (struct file_handle * h, union value * perm, struct dictionary * d
 
   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.) */
@@ -1469,9 +1419,9 @@ sfm_read_case (struct file_handle * h, union value * perm, struct dictionary * d
 
   /* 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;
index b96a0733f6d8e5858467d9bca281089db5b827df..97028a4966f15440b5de0947e3be1436dff5c165 100644 (file)
@@ -35,6 +35,8 @@ char *alloca ();
 #endif
 #endif
 
+#include "sfm.h"
+#include "sfmP.h"
 #include <assert.h>
 #include <stdlib.h>
 #include <ctype.h>
@@ -51,8 +53,6 @@ char *alloca ();
 #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"
@@ -143,13 +143,13 @@ sfm_write_dictionary (struct sfm_write_info *inf)
     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;
@@ -157,7 +157,7 @@ sfm_write_dictionary (struct sfm_write_info *inf)
                : 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;
@@ -227,18 +227,18 @@ write_header (struct sfm_write_info *inf)
   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--)
@@ -247,14 +247,18 @@ write_header (struct sfm_write_info *inf)
 
   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)));
        }
@@ -292,9 +296,15 @@ write_header (struct sfm_write_info *inf)
       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))
@@ -508,11 +518,17 @@ write_documents (struct sfm_write_info * inf)
   }
   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;
index 456e1a710df31305e10618eb09ce8ec0ab934eaa..f6623e2710ac4b28cdd30798772b10a61bfb4351 100644 (file)
--- a/src/som.c
+++ b/src/som.c
    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. */
index c77d84626887ab735c4c39c6183ccaaef7c7c8c1..d68ee45b2a71aebee306bac68a4e7818ed482c6c 100644 (file)
@@ -18,6 +18,7 @@
    02111-1307, USA. */
 
 #include <config.h>
+#include "sort.h"
 #include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -30,7 +31,6 @@
 #include "heap.h"
 #include "lexer.h"
 #include "misc.h"
-#include "sort.h"
 #include "str.h"
 #include "var.h"
 #include "vfm.h"
@@ -111,7 +111,7 @@ parse_sort_variables (void)
       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 ('('))
@@ -485,7 +485,8 @@ allocate_cases (void)
 {
   /* 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;
@@ -501,7 +502,8 @@ allocate_cases (void)
       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;
        }
@@ -727,7 +729,8 @@ write_initial_runs (int separate)
        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));
       }
   }
 
@@ -914,10 +917,11 @@ merge (void)
   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)
@@ -1058,8 +1062,8 @@ merge_once (int run_index[], int run_length[], int n_runs)
          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]))
@@ -1087,8 +1091,9 @@ merge_once (int run_index[], int run_length[], int n_runs)
          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 "
@@ -1116,8 +1121,9 @@ merge_once (int run_index[], int run_length[], int n_runs)
              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]))
@@ -1210,7 +1216,7 @@ lossage:
 
 /* 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);
@@ -1354,7 +1360,7 @@ sort_stream_write (void)
 }
 
 /* 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:
index 29fc432ef0902b4be4bb104f02d68f7e7b6fd1b1..bffcd5b18007d1c135b76e0e77467794fa233560 100644 (file)
@@ -33,23 +33,18 @@ cmd_split_file (void)
   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 ();
index a52ab402dae4fb12be41b42ba491905b6ab83610..4727b938e4446091ee43b7ea33ae0d77bc4f3f07 100644 (file)
    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;
@@ -60,7 +60,7 @@ calc_kurt (const double d[4], double n, double variance)
     (((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.)));
index 81a3f112a72032db225df639e822a33d7a7e236f..46cb7266dc21279fc47f8ff98f1d6940d5433504 100644 (file)
 #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;
index 0a9d0d0f26d713fb64ce6de6b0e3f4cfa0a13377..8912f3e58b6a4ec5921e58a952fd316dcb137560 100644 (file)
--- a/src/str.c
+++ b/src/str.c
@@ -18,6 +18,7 @@
    02111-1307, USA. */
 
 #include <config.h>
+#include "str.h"
 #include <assert.h>
 #include <ctype.h>
 #include <limits.h>
@@ -25,7 +26,6 @@
 #include "alloc.h"
 #include "error.h"
 #include "pool.h"
-#include "str.h"
 \f
 /* sprintf() wrapper functions for convenience. */
 
index 584db1430da30c212f7681ac3464ad05e2892beb..dd33d574f437dbe6f9b3b9ba05c62756ce838554 100644 (file)
@@ -35,7 +35,6 @@
 #include "tab.h"
 #include "value-labels.h"
 #include "var.h"
-#include "vector.h"
 
 /* Constants for DISPLAY utility. */
 enum
@@ -98,8 +97,12 @@ cmd_sysfile_info (void)
   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);
@@ -107,22 +110,25 @@ cmd_sysfile_info (void)
   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);
@@ -130,18 +136,19 @@ cmd_sysfile_info (void)
   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);
@@ -151,7 +158,7 @@ cmd_sysfile_info (void)
   tab_flags (t, SOMF_NO_TITLE);
   tab_submit (t);
 
-  free_dictionary (d);
+  dict_destroy (d);
   
   return lex_end_of_command ();
 }
@@ -184,13 +191,13 @@ cmd_display (void)
       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
@@ -226,7 +233,7 @@ cmd_display (void)
 
       if (token != '.')
        {
-         if (!parse_variables (NULL, &vl, &n, PV_NONE))
+         if (!parse_variables (default_dict, &vl, &n, PV_NONE))
            {
              free (vl);
              return CMD_FAILURE;
@@ -234,7 +241,7 @@ cmd_display (void)
          as = AS_DICTIONARY;
        }
       else
-       fill_all_vars (&vl, &n, FV_NONE);
+       dict_get_vars (default_dict, &vl, &n, 0);
 
       if (as == AS_SCRATCH)
        {
@@ -276,24 +283,27 @@ display_macros (void)
 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--;
@@ -572,10 +582,12 @@ compare_vectors_by_name (const void *a_, const void *b_)
 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."));
@@ -584,7 +596,7 @@ display_vectors (int sorted)
 
   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);
 
index bd043a0f9ed546d1b829d1689d51d469bb4ff350..89270bf8857f8056407461ab5ee32c4f9caee6f5 100644 (file)
@@ -183,17 +183,12 @@ groups_calc (struct ccase * c)
   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? */
@@ -234,7 +229,6 @@ g_postcalc (void)
 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;
@@ -242,17 +236,7 @@ z_calc (struct ccase * c)
   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? */
     {
@@ -548,9 +532,10 @@ tts_custom_pairs (struct cmd_t_test *cmd unused)
   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;
 
@@ -559,7 +544,7 @@ tts_custom_pairs (struct cmd_t_test *cmd unused)
     {
       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))
        {
index 71f8f8ac1860b00e76e162559ab834989af28c6f..7e81b6cc561b9138e45e55804e2fb6a028af578f 100644 (file)
--- a/src/tab.c
+++ b/src/tab.c
@@ -35,6 +35,7 @@ char *alloca ();
 #endif
 #endif
 
+#include "tab.h"
 #include <ctype.h>
 #include <assert.h>
 #include <stdarg.h>
@@ -48,12 +49,11 @@ char *alloca ();
 #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,
index 8aa3eb3e7bf1a5e53213b720b52ecf124ef0ca32..f569028a081b389b632f42babebbcf0c9596d3aa 100644 (file)
@@ -58,10 +58,9 @@ cmd_temporary (void)
       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
@@ -71,233 +70,17 @@ cmd_temporary (void)
   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;
     }
index 2642b9c4af90ee9f38a1f344037ed0f89072784e..dca7b4760777b96e267808719b6dcf3930f41c38 100644 (file)
@@ -93,10 +93,7 @@ cmd_file_label (void)
   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;
@@ -107,14 +104,22 @@ cmd_file_label (void)
 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. */
@@ -126,7 +131,7 @@ cmd_document (void)
     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):"),
@@ -169,9 +174,7 @@ cmd_drop_documents (void)
   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 ();
 }
index 46fa725508e669f11251b5c4704c9cc6b9cbd1c8..69709820ed5f20782cfc70647a10e75b3a299e8b 100644 (file)
@@ -94,7 +94,7 @@ do_value_labels (int erase)
   
   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 != '.')
index a7e80a595e71c0808bdd225902ce79192784ff8f..39c1005e90f08e48ab5c4cefaffcb774c6bd83ef 100644 (file)
    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;
@@ -91,8 +91,12 @@ val_labs_set_width (struct val_labs *vls, int new_width)
 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. */
index 82d49d1e9741f889c6dd25b24ee7672a34d2aaf8..bc22439669c49b919def5785a67af970e7b5d344 100644 (file)
@@ -46,7 +46,7 @@ cmd_variable_labels (void)
   lex_match ('/');
   do
     {
-      parse_variables (NULL, &v, &nv, PV_NONE);
+      parse_variables (default_dict, &v, &nv, PV_NONE);
 
       if (token != T_STRING)
        {
index a5a7357005b6776adc2ed43dbf735567ffd822f1..cc384153b7c28fb469e5de121515fa77e401ebad 100644 (file)
--- a/src/var.h
+++ b/src/var.h
@@ -20,6 +20,7 @@
 #if !var_h
 #define var_h 1
 
+#include <stddef.h>
 #include "format.h"
 
 /* Values. */
@@ -110,14 +111,6 @@ struct freq_tab
     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. */
 
@@ -145,7 +138,9 @@ enum
 
 struct frequencies_proc
   {
-    /* General mode. */
+    int used;                   /* 1=This variable already used. */
+
+    /* Freqency table. */
     struct freq_tab tab;       /* Frequencies table to use. */
 
     /* Percentiles. */
@@ -197,7 +192,7 @@ struct descriptives_proc
 /* GET private data. */
 struct get_proc
   {
-    int fv, nv;                        /* First, last, # of values. */
+    int fv, nv;                        /* First, # of values. */
   };
 
 /* Sort order. */
@@ -213,14 +208,6 @@ struct sort_cases_proc
     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
   {
@@ -293,13 +280,12 @@ struct variable
     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. */
@@ -314,6 +300,7 @@ struct variable
     char *label;               /* Variable label. */
 
     /* Per-procedure info. */
+    void *aux;
     struct get_proc get;
     union
       {
@@ -323,7 +310,6 @@ struct variable
        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;
       }
@@ -332,6 +318,26 @@ struct variable
 
 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. */
 
@@ -345,34 +351,74 @@ struct ccase
 /* 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. */
 
@@ -405,19 +451,6 @@ void cancel_temporary (void);
 \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 *);
@@ -440,32 +473,6 @@ struct variable *force_dup_variable (struct dictionary *,
        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. */
 
@@ -494,29 +501,40 @@ extern int f_trns;
 
 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 */
index 2a723d96dffed427d90641800eadadeac483179c..d1bbd610805f4067537ed0d7fb634e7b40135086 100644 (file)
@@ -18,6 +18,7 @@
    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)
@@ -78,10 +55,6 @@ discard_variables (void)
 
   ctl_stack = NULL;
 
-  free (vec);
-  vec = NULL;
-  nvec = 0;
-
   expr_free (process_if_expr);
   process_if_expr = NULL;
 
@@ -90,269 +63,6 @@ discard_variables (void)
   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
index 288e0510312f6111ac87ee58743640d26a0cad55..d5001b2dd71c37d5b97eaf51d3ebbc8ce6d2f301 100644 (file)
@@ -35,6 +35,7 @@ char *alloca ();
 #endif
 #endif
 
+#include "var.h"
 #include <assert.h>
 #include <ctype.h>
 #include <stdlib.h>
@@ -45,124 +46,121 @@ char *alloca ();
 #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))
     {
@@ -173,51 +171,34 @@ parse_variables (struct dictionary * dict, struct variable *** v, int *nv, int p
   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");
@@ -233,15 +214,17 @@ parse_variables (struct dictionary * dict, struct variable *** v, int *nv, int p
                  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;
                }
            }
@@ -249,9 +232,9 @@ parse_variables (struct dictionary * dict, struct variable *** v, int *nv, int p
            {
              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);
@@ -265,62 +248,60 @@ parse_variables (struct dictionary * dict, struct variable *** v, int *nv, int p
          *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;
 
@@ -329,7 +310,7 @@ fail:
   *v = NULL;
   *nv = 0;
   if (!(pv_opts & PV_DUPLICATE))
-    local_free (bits);
+    free (included);
   return 0;
 }
 
@@ -386,6 +367,12 @@ parse_DATA_LIST_vars (char ***names, int *nnames, int pv_opts)
   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
@@ -488,12 +475,16 @@ fail:
 
 /* 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;
@@ -501,12 +492,12 @@ parse_mixed_vars (char ***names, int *nnames, int pv_opts)
     }
   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++)
@@ -527,3 +518,160 @@ fail:
   *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;
+}
index acaa07870a5c8bd96e7818a03f72c8f39ad4c132..e63ac2153f6166eef9d1dcc0694ab539ac9308bc 100644 (file)
 #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)
@@ -51,10 +44,6 @@ 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);
@@ -81,7 +70,7 @@ cmd_vector (void)
                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;
@@ -98,6 +87,8 @@ cmd_vector (void)
       if (lex_match ('='))
        {
          /* Long form. */
+          struct variable **v;
+          int nv;
 
          if (strchr (vecnames, '\0')[1])
            {
@@ -108,16 +99,12 @@ cmd_vector (void)
              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 ('('))
        {
@@ -130,6 +117,10 @@ cmd_vector (void)
          /* 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 ();
@@ -162,7 +153,7 @@ cmd_vector (void)
              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;
@@ -172,23 +163,21 @@ cmd_vector (void)
            }
 
          /* 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
        {
@@ -212,19 +201,5 @@ cmd_vector (void)
 
 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;
-}
diff --git a/src/vector.h b/src/vector.h
deleted file mode 100644 (file)
index c75f569..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/* 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 */
index 3fdefb5db2940dd609ab813133d95207d0a8263f..17bd9f266e58e18fa4f67bf745bface9ec0556ec 100644 (file)
--- a/src/vfm.c
+++ b/src/vfm.c
@@ -35,6 +35,8 @@ char *alloca ();
 #endif
 #endif
 
+#include "vfm.h"
+#include "vfmP.h"
 #include <assert.h>
 #include <errno.h>
 #include <stdio.h>
@@ -53,10 +55,7 @@ char *alloca ();
 #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):
@@ -158,7 +157,7 @@ procedure (void (*beginfunc) (void),
   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;
@@ -298,9 +297,10 @@ prepare_for_writing (void)
      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)
     {
@@ -330,19 +330,24 @@ arrange_compaction (void)
     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 ();
@@ -426,19 +431,14 @@ vector_initialization (void)
 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;
     }
 }
 
@@ -455,7 +455,8 @@ setup_lag (void)
   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
@@ -504,7 +505,7 @@ open_active_file (void)
   if (!temporary)
     {
       temp_trns = n_trns;
-      temp_dict = &default_dict;
+      temp_dict = default_dict;
     }
 
   /* No cases passed to the procedure yet. */
@@ -552,12 +553,14 @@ close_active_file (void)
      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)
@@ -574,9 +577,7 @@ close_active_file (void)
   /* Old data sink is gone now. */
   vfm_sink = NULL;
 
-  /* Finish compaction. */
-  if (compaction_necessary)
-    finish_compaction ();
+  /* Cancel TEMPORARY. */
   cancel_temporary ();
 
   /* Free temporary cases. */
@@ -591,8 +592,8 @@ close_active_file (void)
   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 ();
@@ -604,18 +605,10 @@ close_active_file (void)
   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"));
 }
@@ -950,7 +943,8 @@ lag_case (void)
 {
   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;
 }
@@ -1001,8 +995,9 @@ procedure_write_case (void)
          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? */
@@ -1102,20 +1097,23 @@ cancel_transformations (void)
 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;
 
@@ -1147,7 +1145,9 @@ static int
 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. */
@@ -1167,9 +1167,11 @@ SPLIT_FILE_procfunc (struct ccase *c)
 
   /* 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)
        {
@@ -1208,6 +1210,7 @@ compact_case (struct ccase *dest, const struct ccase *src)
 {
   int i;
   int nval = 0;
+  size_t var_cnt;
   
   assert (compaction_necessary);
 
@@ -1220,9 +1223,10 @@ compact_case (struct ccase *dest, const struct ccase *src)
 
   /* 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;
@@ -1243,35 +1247,18 @@ compact_case (struct ccase *dest, const struct ccase *src)
 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);
 }
 
   
index 1d7fe9eb306f35bbecb3f041d7626ce8e42b4d06..642a2b736fdd69b304d56c4ac163400b39b8bdcd 100644 (file)
@@ -47,7 +47,7 @@ cmd_weight (void)
   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;
@@ -67,55 +67,8 @@ cmd_weight (void)
          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;
-}