From 12895f38b01137ae0b14f07d26e6f0928b735bdf Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Sat, 8 Aug 2009 20:34:28 -0700 Subject: [PATCH] Add UP_CAST macro, for safer casting from contained data to its container. --- src/language/control/repeat.c | 20 ++++++++++------- src/language/stats/chisquare.c | 4 +++- src/language/stats/npar.q | 3 ++- src/language/syntax-file.c | 17 ++++++++++----- src/language/syntax-string-source.c | 11 ++++++---- src/libpspp/cast.h | 34 +++++++++++++++++++++++++++++ src/math/box-whisker.c | 11 +++++----- src/math/histogram.c | 5 +++-- src/math/np.c | 7 +++--- src/math/percentiles.c | 6 +++-- src/math/trimmed-mean.c | 8 ++++--- src/math/tukey-hinges.c | 4 +++- src/output/charts/box-whisker.c | 5 +++-- src/output/charts/np-plot.c | 10 +++++---- src/output/charts/piechart.c | 5 +++-- src/output/charts/plot-hist.c | 5 +++-- src/ui/gui/find-dialog.c | 7 ++++-- src/ui/gui/syntax-editor-source.c | 4 +++- src/ui/terminal/read-line.c | 4 ++-- 19 files changed, 119 insertions(+), 51 deletions(-) create mode 100644 src/libpspp/cast.h diff --git a/src/language/control/repeat.c b/src/language/control/repeat.c index 32847bb4..cb608f76 100644 --- a/src/language/control/repeat.c +++ b/src/language/control/repeat.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2007 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2007, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -512,10 +513,10 @@ find_substitution (struct repeat_block *block, struct substring name) /* Makes appropriate DO REPEAT macro substitutions within the repeated lines. */ static void -do_repeat_filter (struct getl_interface *block_, - struct string *line) +do_repeat_filter (struct getl_interface *interface, struct string *line) { - struct repeat_block *block = (struct repeat_block *) block_; + struct repeat_block *block + = UP_CAST (interface, struct repeat_block, parent); bool in_apos, in_quote, dot; struct substring input; struct string output; @@ -557,7 +558,8 @@ do_repeat_filter (struct getl_interface *block_, static struct repeat_line * current_line (const struct getl_interface *interface) { - struct repeat_block *block = (struct repeat_block *) interface; + struct repeat_block *block + = UP_CAST (interface, struct repeat_block, parent); return (block->cur_line != ll_null (&block->lines) ? ll_data (block->cur_line, struct repeat_line, ll) : NULL); @@ -570,7 +572,8 @@ static bool do_repeat_read (struct getl_interface *interface, struct string *output) { - struct repeat_block *block = (struct repeat_block *) interface; + struct repeat_block *block + = UP_CAST (interface, struct repeat_block, parent); struct repeat_line *line; block->cur_line = ll_next (block->cur_line); @@ -591,9 +594,10 @@ do_repeat_read (struct getl_interface *interface, /* Frees a DO REPEAT block. Called by getl to close out the DO REPEAT block. */ static void -do_repeat_close (struct getl_interface *block_) +do_repeat_close (struct getl_interface *interface) { - struct repeat_block *block = (struct repeat_block *) block_; + struct repeat_block *block + = UP_CAST (interface, struct repeat_block, parent); pool_destroy (block->pool); } diff --git a/src/language/stats/chisquare.c b/src/language/stats/chisquare.c index 5c20896a..71857cfb 100644 --- a/src/language/stats/chisquare.c +++ b/src/language/stats/chisquare.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -305,7 +306,8 @@ chisquare_execute (const struct dataset *ds, { const struct dictionary *dict = dataset_dict (ds); int v, i; - struct chisquare_test *cst = (struct chisquare_test *) test; + struct chisquare_test *cst = UP_CAST (test, struct chisquare_test, + parent.parent); struct one_sample_test *ost = &cst->parent; int n_cells = 0; double total_expected = 0.0; diff --git a/src/language/stats/npar.q b/src/language/stats/npar.q index c8c44e6d..8c6f98f8 100644 --- a/src/language/stats/npar.q +++ b/src/language/stats/npar.q @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -585,7 +586,7 @@ one_sample_insert_variables (const struct npar_test *test, struct const_hsh_table *var_hash) { int i; - struct one_sample_test *ost = (struct one_sample_test *) test; + struct one_sample_test *ost = UP_CAST (test, struct one_sample_test, parent); for ( i = 0 ; i < ost->n_vars ; ++i ) const_hsh_insert (var_hash, ost->vars[i]); diff --git a/src/language/syntax-file.c b/src/language/syntax-file.c index 678d2f51..411022d4 100644 --- a/src/language/syntax-file.c +++ b/src/language/syntax-file.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -62,14 +63,16 @@ struct syntax_file_source static const char * name (const struct getl_interface *s) { - const struct syntax_file_source *sfs = (const struct syntax_file_source *) s; + const struct syntax_file_source *sfs = UP_CAST (s, struct syntax_file_source, + parent); return sfs->fn; } static int line_number (const struct getl_interface *s) { - const struct syntax_file_source *sfs = (const struct syntax_file_source *) s; + const struct syntax_file_source *sfs = UP_CAST (s, struct syntax_file_source, + parent); return sfs->ln; } @@ -80,7 +83,8 @@ static bool read_syntax_file (struct getl_interface *s, struct string *line) { - struct syntax_file_source *sfs = (struct syntax_file_source *) s; + struct syntax_file_source *sfs = UP_CAST (s, struct syntax_file_source, + parent); /* Open file, if not yet opened. */ if (sfs->syntax_file == NULL) @@ -120,7 +124,8 @@ read_syntax_file (struct getl_interface *s, static void syntax_close (struct getl_interface *s) { - struct syntax_file_source *sfs = (struct syntax_file_source *) s; + struct syntax_file_source *sfs = UP_CAST (s, struct syntax_file_source, + parent); if (sfs->syntax_file && EOF == fn_close (sfs->fn, sfs->syntax_file)) msg (MW, _("Closing `%s': %s."), sfs->fn, strerror (errno)); @@ -150,6 +155,6 @@ create_syntax_file_source (const char *fn) ss->parent.name = name ; ss->parent.location = line_number; - return (struct getl_interface *) ss; + return &ss->parent; } diff --git a/src/language/syntax-string-source.c b/src/language/syntax-string-source.c index 94a56f97..405141cd 100644 --- a/src/language/syntax-string-source.c +++ b/src/language/syntax-string-source.c @@ -1,5 +1,5 @@ /* PSPPIRE - a graphical interface for PSPP. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,6 +17,7 @@ #include +#include #include #include #include @@ -60,7 +61,8 @@ location (const struct getl_interface *i UNUSED) static void do_close (struct getl_interface *i ) { - struct syntax_string_source *sss = (struct syntax_string_source *) i; + struct syntax_string_source *sss = UP_CAST (i, struct syntax_string_source, + parent); ds_destroy (&sss->buffer); @@ -73,7 +75,8 @@ static bool read_single_line (struct getl_interface *i, struct string *line) { - struct syntax_string_source *sss = (struct syntax_string_source *) i; + struct syntax_string_source *sss = UP_CAST (i, struct syntax_string_source, + parent); size_t next; @@ -120,7 +123,7 @@ create_syntax_string_source (const char *format, ...) sss->parent.location = location; - return (struct getl_interface *) sss; + return &sss->parent; } /* Return the syntax currently contained in S. diff --git a/src/libpspp/cast.h b/src/libpspp/cast.h new file mode 100644 index 00000000..f74442c2 --- /dev/null +++ b/src/libpspp/cast.h @@ -0,0 +1,34 @@ +/* PSPP - a program for statistical analysis. + Copyright (C) 2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 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, see . */ + +#ifndef LIBPSPP_CAST_H +#define LIBPSPP_CAST_H 1 + +#include + +/* Given expressions A and B, both of which have pointer type, + expands to a void expression that causes a compiler warning if + A and B are not pointers to qualified or unqualified versions + of compatible types. */ +#define CHECK_POINTER_COMPATIBILITY(A, B) ((void) sizeof ((A) == (B))) + +/* Given POINTER, a pointer to the given MEMBER within structure + STRUCT, returns the address of the STRUCT. */ +#define UP_CAST(POINTER, STRUCT, MEMBER) \ + (CHECK_POINTER_COMPATIBILITY (&((STRUCT *) 0)->MEMBER, POINTER), \ + (STRUCT *) ((char *) (POINTER) - offsetof (STRUCT, MEMBER))) + +#endif /* libpspp/cast.h */ diff --git a/src/math/box-whisker.c b/src/math/box-whisker.c index 3712235e..de4124ef 100644 --- a/src/math/box-whisker.c +++ b/src/math/box-whisker.c @@ -20,6 +20,7 @@ #include "tukey-hinges.h" #include #include +#include #include #include #include @@ -30,8 +31,8 @@ static void destroy (struct statistic *s) { - struct order_stats *os = (struct order_stats *) s; - struct box_whisker *bw = (struct box_whisker *) s; + struct box_whisker *bw = UP_CAST (s, struct box_whisker, parent.parent); + struct order_stats *os = &bw->parent; struct ll *ll; for (ll = ll_head (&bw->outliers); ll != ll_null (&bw->outliers); ) @@ -53,7 +54,7 @@ static void acc (struct statistic *s, const struct ccase *cx, double c UNUSED, double cc UNUSED, double y) { - struct box_whisker *bw = (struct box_whisker *) s; + struct box_whisker *bw = UP_CAST (s, struct box_whisker, parent.parent); bool extreme; struct outlier *o; @@ -115,8 +116,8 @@ box_whisker_create (const struct tukey_hinges *th, const struct variable *id_var, size_t casenumber_idx) { struct box_whisker *w = xzalloc (sizeof (*w)); - struct order_stats *os = (struct order_stats *) w; - struct statistic *stat = (struct statistic *) w; + struct order_stats *os = &w->parent; + struct statistic *stat = &os->parent; os->n_k = 0; diff --git a/src/math/histogram.c b/src/math/histogram.c index c41bdc08..3c88c385 100644 --- a/src/math/histogram.c +++ b/src/math/histogram.c @@ -19,6 +19,7 @@ #include #include +#include #include #include "chart-geometry.h" @@ -37,7 +38,7 @@ histogram_add (struct histogram *h, double y, double c) static void acc (struct statistic *s, const struct ccase *cx UNUSED, double c, double cc UNUSED, double y) { - struct histogram *hist = (struct histogram *) s; + struct histogram *hist = UP_CAST (s, struct histogram, parent); gsl_histogram_accumulate (hist->gsl_hist, y, c); } @@ -46,7 +47,7 @@ acc (struct statistic *s, const struct ccase *cx UNUSED, double c, double cc UNU static void destroy (struct statistic *s) { - struct histogram *h = (struct histogram *) s; + struct histogram *h = UP_CAST (s, struct histogram, parent); gsl_histogram_free (h->gsl_hist); free (s); } diff --git a/src/math/np.c b/src/math/np.c index d36acc2a..b6318209 100644 --- a/src/math/np.c +++ b/src/math/np.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -32,8 +33,8 @@ static void destroy (struct statistic *stat) { - struct order_stats *os = (struct order_stats *) stat; - free (os); + struct np *np = UP_CAST (stat, struct np, parent.parent); + free (np); } @@ -42,7 +43,7 @@ acc (struct statistic *s, const struct ccase *cx UNUSED, double c, double cc, double y) { struct ccase *cp; - struct np *np = (struct np *) s; + struct np *np = UP_CAST (s, struct np, parent.parent); double rank = np->prev_cc + (c + 1) / 2.0; double ns = gsl_cdf_ugaussian_Pinv (rank / ( np->n + 1 )); diff --git a/src/math/percentiles.c b/src/math/percentiles.c index 3aec0c96..2bde9d6f 100644 --- a/src/math/percentiles.c +++ b/src/math/percentiles.c @@ -24,6 +24,7 @@ #define N_(msgid) msgid #include +#include #include #include #include @@ -154,9 +155,10 @@ percentile_calculate (const struct percentile *ptl, enum pc_alg alg) static void destroy (struct statistic *stat) { - struct order_stats *os = (struct order_stats *) stat; + struct percentile *ptl = UP_CAST (stat, struct percentile, parent.parent); + struct order_stats *os = &ptl->parent; free (os->k); - free (os); + free (ptl); } diff --git a/src/math/trimmed-mean.c b/src/math/trimmed-mean.c index 6e43f7b0..d1cc6b70 100644 --- a/src/math/trimmed-mean.c +++ b/src/math/trimmed-mean.c @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -27,7 +28,7 @@ static void acc (struct statistic *s, const struct ccase *cx UNUSED, double c, double cc, double y) { - struct trimmed_mean *tm = (struct trimmed_mean *) s; + struct trimmed_mean *tm = UP_CAST (s, struct trimmed_mean, parent.parent); struct order_stats *os = &tm->parent; if ( cc > os->k[0].tc && cc < os->k[1].tc) @@ -40,9 +41,10 @@ acc (struct statistic *s, const struct ccase *cx UNUSED, double c, double cc, do static void destroy (struct statistic *s) { - struct order_stats *os = (struct order_stats *) s; + struct trimmed_mean *tm = UP_CAST (s, struct trimmed_mean, parent.parent); + struct order_stats *os = &tm->parent; free (os->k); - free (s); + free (tm); } struct trimmed_mean * diff --git a/src/math/tukey-hinges.c b/src/math/tukey-hinges.c index ded7a9c6..22ab4521 100644 --- a/src/math/tukey-hinges.c +++ b/src/math/tukey-hinges.c @@ -20,6 +20,7 @@ #include #include +#include #include void @@ -59,7 +60,8 @@ tukey_hinges_calculate (const struct tukey_hinges *th, double hinge[3]) static void destroy (struct statistic *s) { - struct order_stats *os = (struct order_stats *) s; + struct tukey_hinges *th = UP_CAST (s, struct tukey_hinges, parent.parent); + struct order_stats *os = &th->parent; free (os->k); free (s); diff --git a/src/output/charts/box-whisker.c b/src/output/charts/box-whisker.c index ba3df290..5fd9d295 100644 --- a/src/output/charts/box-whisker.c +++ b/src/output/charts/box-whisker.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -221,7 +222,7 @@ static void boxplot_chart_draw (const struct chart *chart, cairo_t *cr, struct chart_geometry *geom) { - const struct boxplot *boxplot = (struct boxplot *) chart; + const struct boxplot *boxplot = UP_CAST (chart, struct boxplot, chart); double box_width; size_t i; @@ -240,7 +241,7 @@ boxplot_chart_draw (const struct chart *chart, cairo_t *cr, static void boxplot_chart_destroy (struct chart *chart) { - struct boxplot *boxplot = (struct boxplot *) chart; + struct boxplot *boxplot = UP_CAST (chart, struct boxplot, chart); size_t i; free (boxplot->title); diff --git a/src/output/charts/np-plot.c b/src/output/charts/np-plot.c index 565b5e14..c077b872 100644 --- a/src/output/charts/np-plot.c +++ b/src/output/charts/np-plot.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -124,7 +125,8 @@ static void np_plot_chart_draw (const struct chart *chart, cairo_t *cr, struct chart_geometry *geom) { - const struct np_plot_chart *npp = (struct np_plot_chart *) chart; + const struct np_plot_chart *npp = UP_CAST (chart, struct np_plot_chart, + chart); struct casereader *data; struct ccase *c; @@ -151,7 +153,8 @@ static void dnp_plot_chart_draw (const struct chart *chart, cairo_t *cr, struct chart_geometry *geom) { - const struct np_plot_chart *dnpp = (struct np_plot_chart *) chart; + const struct np_plot_chart *dnpp = UP_CAST (chart, struct np_plot_chart, + chart); struct casereader *data; struct ccase *c; @@ -174,8 +177,7 @@ dnp_plot_chart_draw (const struct chart *chart, cairo_t *cr, static void np_plot_chart_destroy (struct chart *chart) { - struct np_plot_chart *npp = (struct np_plot_chart *) chart; - + struct np_plot_chart *npp = UP_CAST (chart, struct np_plot_chart, chart); casereader_destroy (npp->data); free (npp->label); free (npp); diff --git a/src/output/charts/piechart.c b/src/output/charts/piechart.c index c6e6b24f..935c6eb0 100644 --- a/src/output/charts/piechart.c +++ b/src/output/charts/piechart.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -80,7 +81,7 @@ static void piechart_draw (const struct chart *chart, cairo_t *cr, struct chart_geometry *geom) { - struct piechart *pie = (struct piechart *) chart; + const struct piechart *pie = UP_CAST (chart, struct piechart, chart); double total_magnitude; double left_label, right_label; double centre_x, centre_y; @@ -176,7 +177,7 @@ draw_segment(cairo_t *cr, static void piechart_destroy (struct chart *chart) { - struct piechart *pie = (struct piechart *) chart; + struct piechart *pie = UP_CAST (chart, struct piechart, chart); int i; free (pie->title); diff --git a/src/output/charts/plot-hist.c b/src/output/charts/plot-hist.c index 34c98aa2..db3d89ba 100644 --- a/src/output/charts/plot-hist.c +++ b/src/output/charts/plot-hist.c @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -146,7 +147,7 @@ static void histogram_chart_draw (const struct chart *chart, cairo_t *cr, struct chart_geometry *geom) { - struct histogram_chart *h = (struct histogram_chart *) chart; + struct histogram_chart *h = UP_CAST (chart, struct histogram_chart, chart); int i; int bins; @@ -208,7 +209,7 @@ histogram_chart_draw (const struct chart *chart, cairo_t *cr, static void histogram_chart_destroy (struct chart *chart) { - struct histogram_chart *h = (struct histogram_chart *) chart; + struct histogram_chart *h = UP_CAST (chart, struct histogram_chart, chart); if (h->gsl_hist != NULL) gsl_histogram_free (h->gsl_hist); free (h->label); diff --git a/src/ui/gui/find-dialog.c b/src/ui/gui/find-dialog.c index a02ed6e2..3d3aed88 100644 --- a/src/ui/gui/find-dialog.c +++ b/src/ui/gui/find-dialog.c @@ -34,6 +34,7 @@ which match particular strings */ #include #include #include +#include #include #include @@ -564,7 +565,8 @@ regexp_label_compare (const struct comparator *cmptr, static void regexp_destroy (struct comparator *cmptr) { - struct regexp_comparator *rec = (struct regexp_comparator *) cmptr; + struct regexp_comparator *rec + = UP_CAST (cmptr, struct regexp_comparator, parent); regfree (&rec->re); } @@ -572,7 +574,8 @@ regexp_destroy (struct comparator *cmptr) static void cmptr_value_destroy (struct comparator *cmptr) { - struct value_comparator *vc = (struct value_comparator *) cmptr; + struct value_comparator *vc + = UP_CAST (cmptr, struct value_comparator, parent); value_destroy (&vc->pattern, var_get_width (cmptr->var)); } diff --git a/src/ui/gui/syntax-editor-source.c b/src/ui/gui/syntax-editor-source.c index b4a8918f..6ec866c9 100644 --- a/src/ui/gui/syntax-editor-source.c +++ b/src/ui/gui/syntax-editor-source.c @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -72,7 +73,8 @@ read_line_from_buffer (struct getl_interface *i, gchar *text; GtkTextIter next_line; - struct syntax_editor_source *ses = (struct syntax_editor_source *) i; + struct syntax_editor_source *ses + = UP_CAST (i, struct syntax_editor_source, parent); if ( gtk_text_iter_compare (&ses->i, &ses->end) >= 0) return false; diff --git a/src/ui/terminal/read-line.c b/src/ui/terminal/read-line.c index 5c9baa5b..f85e4e76 100644 --- a/src/ui/terminal/read-line.c +++ b/src/ui/terminal/read-line.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -107,8 +108,7 @@ static bool read_interactive (struct getl_interface *s, struct string *line) { - struct readln_source *is = - (struct readln_source *) s ; + struct readln_source *is = UP_CAST (s, struct readln_source, parent); return is->interactive_func (line, prompt_get_style ()); } -- 2.30.2