X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Frecode.c;h=98e6dfdd2d0ecf1cddf842db228129439363b95f;hb=4fdeb2145d081ff1b84e3f6c99f9d1c048c0d64a;hp=146e8a36a5b28e102558638a16b85bd18cd9cf8b;hpb=fcb9e49b2a2d57af7c001ae5d2eda9ac443ba36b;p=pspp-builds.git diff --git a/src/recode.c b/src/recode.c index 146e8a36..98e6dfdd 100644 --- a/src/recode.c +++ b/src/recode.c @@ -14,27 +14,27 @@ 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. */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ #include -#include +#include "error.h" #include +#include #include #include "alloc.h" -#include "approx.h" -#include "cases.h" +#include "case.h" #include "command.h" +#include "dictionary.h" #include "error.h" #include "lexer.h" #include "magic.h" #include "str.h" #include "var.h" - -#include "debug-print.h" /* Definitions. */ +/* Type of source value for RECODE. */ enum { RCD_END, /* sentinel value */ @@ -66,7 +66,7 @@ struct rcd_var struct variable *src; /* Source variable. */ struct variable *dest; /* Destination variable. */ - char dest_name[9]; /* Name of dest variable if we're creating it. */ + char dest_name[LONG_NAME_LEN + 1]; /* Name of dest variable if we're creating it. */ int has_sysmis; /* Do we recode for SYSMIS? */ union value sysmis; /* Coding for SYSMIS (if src is numeric). */ @@ -105,23 +105,12 @@ struct recode_trns static int parse_dest_spec (struct rcd_var * rcd, union value *v, size_t *max_dst_width); static int parse_src_spec (struct rcd_var * rcd, int type, size_t max_src_width); -static int recode_trns_proc (struct trns_header *, struct ccase *); -static void recode_trns_free (struct trns_header *); -static double convert_to_double (char *, int); - -#if DEBUGGING -static void debug_print (struct rcd_var * head); -#endif +static trns_proc_func recode_trns_proc; +static trns_free_func recode_trns_free; +static double convert_to_double (const char *, int); /* Parser. */ -/* First transformation in the list. rcd is in this list. */ -static struct rcd_var *head; - -/* Variables in the current part of the recoding. */ -struct variable **v; -int nv; - /* Parses the RECODE transformation. */ int cmd_recode (void) @@ -148,10 +137,16 @@ cmd_recode (void) rcd_var's. */ struct recode_trns *trns; - lex_match_id ("RECODE"); + /* First transformation in the list. rcd is in this list. */ + struct rcd_var *head; + + /* Variables in the current part of the recoding. */ + struct variable **v; + int nv; /* Parses each specification between slashes. */ head = rcd = xmalloc (sizeof *rcd); + v = NULL; for (;;) { /* Whether we've already encountered a specification for SYSMIS. */ @@ -165,7 +160,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 @@ -239,7 +234,7 @@ cmd_recode (void) else { for (i = mark; i < rcd->nmap; i++) - rcd->map[i].t.c = xstrdup (output.c); + rcd->map[i].t.c = (output.c?xstrdup (output.c):NULL); free (output.c); } } @@ -295,7 +290,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 +316,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) { @@ -395,13 +390,14 @@ cmd_recode (void) } + free (v); + v = NULL; + if (!lex_match ('/')) break; while (rcd->next) rcd = rcd->next; rcd = rcd->next = xmalloc (sizeof *rcd); - - free (v); } if (token != '.') @@ -413,17 +409,14 @@ 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); - assert (rcd->dest != NULL); + /* FIXME: This can occur if a destname is duplicated. + We could give an error at parse time but I don't + care enough. */ + rcd->dest = dict_lookup_var_assert (default_dict, rcd->dest_name); } - else - envector (rcd->dest); } trns = xmalloc (sizeof *trns); @@ -432,13 +425,10 @@ cmd_recode (void) trns->codings = head; add_transformation ((struct trns_header *) trns); -#if DEBUGGING - debug_print (head); -#endif - return CMD_SUCCESS; lossage: + free (v); { struct recode_trns t; @@ -455,7 +445,7 @@ parse_dest_spec (struct rcd_var * rcd, union value * v, size_t *max_dst_width) v->c = NULL; - if (token == T_NUM) + if (lex_is_number ()) { v->f = tokval; lex_get (); @@ -473,7 +463,7 @@ parse_dest_spec (struct rcd_var * rcd, union value * v, size_t *max_dst_width) if (toklen > max) max = toklen; v->c = xmalloc (max + 1); - st_pad_copy (v->c, ds_value (&tokstr), max + 1); + st_pad_copy (v->c, ds_c_str (&tokstr), max + 1); flags = RCD_DEST_STRING; *max_dst_width = max; lex_get (); @@ -491,6 +481,11 @@ parse_dest_spec (struct rcd_var * rcd, union value * v, size_t *max_dst_width) v->c = NULL; } } + else + { + lex_error (_("expecting output value")); + return 0; + } if ((rcd->flags & RCD_DEST_MASK) == RCD_DEST_ERROR) rcd->flags |= flags; @@ -545,7 +540,7 @@ parse_src_spec (struct rcd_var * rcd, int type, size_t max_src_width) return 0; if (lex_match_id ("HI") || lex_match_id ("HIGHEST")) c->type = RCD_ELSE; - else if (token == T_NUM) + else if (lex_is_number ()) { c->type = RCD_LOW; c->f1.f = tokval; @@ -573,7 +568,7 @@ parse_src_spec (struct rcd_var * rcd, int type, size_t max_src_width) return 0; } } - else if (token == T_NUM) + else if (lex_is_number ()) { c->f1.f = tokval; lex_get (); @@ -581,7 +576,7 @@ parse_src_spec (struct rcd_var * rcd, int type, size_t max_src_width) { if (lex_match_id ("HI") || lex_match_id ("HIGHEST")) c->type = RCD_HIGH; - else if (token == T_NUM) + else if (lex_is_number ()) { c->type = RCD_RANGE; c->f2.f = tokval; @@ -631,7 +626,7 @@ parse_src_spec (struct rcd_var * rcd, int type, size_t max_src_width) if (!lex_force_string ()) return 0; c->f1.c = xmalloc (max_src_width + 1); - st_pad_copy (c->f1.c, ds_value (&tokstr), max_src_width + 1); + st_pad_copy (c->f1.c, ds_c_str (&tokstr), max_src_width + 1); lex_get (); } } @@ -694,7 +689,7 @@ recode_trns_free (struct trns_header * t) static inline struct coding * find_src_numeric (struct rcd_var * v, struct ccase * c) { - double cmp = c->data[v->src->fv].f; + double cmp = case_num (c, v->src->fv); struct coding *cp; if (cmp == SYSMIS) @@ -702,9 +697,9 @@ find_src_numeric (struct rcd_var * v, struct ccase * c) if (v->sysmis.f != -SYSMIS) { if ((v->flags & RCD_DEST_MASK) == RCD_DEST_NUMERIC) - c->data[v->dest->fv].f = v->sysmis.f; + case_data_rw (c, v->dest->fv)->f = v->sysmis.f; else - memcpy (c->data[v->dest->fv].s, v->sysmis.c, + memcpy (case_data_rw (c, v->dest->fv)->s, v->sysmis.s, v->dest->width); } return NULL; @@ -720,19 +715,19 @@ find_src_numeric (struct rcd_var * v, struct ccase * c) return cp; break; case RCD_SINGLE: - if (approx_eq (cmp, cp->f1.f)) + if (cmp == cp->f1.f) return cp; break; case RCD_HIGH: - if (approx_ge (cmp, cp->f1.f)) + if (cmp >= cp->f1.f) return cp; break; case RCD_LOW: - if (approx_le (cmp, cp->f1.f)) + if (cmp <= cp->f1.f) return cp; break; case RCD_RANGE: - if (approx_in_range (cmp, cp->f1.f, cp->f2.f)) + if (cmp >= cp->f1.f && cmp <= cp->f2.f) return cp; break; case RCD_ELSE: @@ -745,7 +740,7 @@ find_src_numeric (struct rcd_var * v, struct ccase * c) static inline struct coding * find_src_string (struct rcd_var * v, struct ccase * c) { - char *cmp = c->data[v->src->fv].s; + const char *cmp = case_str (c, v->src->fv); int w = v->src->width; struct coding *cp; @@ -765,7 +760,7 @@ find_src_string (struct rcd_var * v, struct ccase * c) double f = convert_to_double (cmp, w); if (f != -SYSMIS) { - c->data[v->dest->fv].f = f; + case_data_rw (c, v->dest->fv)->f = f; return NULL; } break; @@ -776,13 +771,15 @@ find_src_string (struct rcd_var * v, struct ccase * c) } static int -recode_trns_proc (struct trns_header * t, struct ccase * c) +recode_trns_proc (struct trns_header * t, struct ccase * c, + int case_idx UNUSED) { struct rcd_var *v; - struct coding *cp; for (v = ((struct recode_trns *) t)->codings; v; v = v->next) { + struct coding *cp; + switch (v->flags & RCD_SRC_MASK) { case RCD_SRC_NUMERIC: @@ -791,6 +788,9 @@ recode_trns_proc (struct trns_header * t, struct ccase * c) case RCD_SRC_STRING: cp = find_src_string (v, c); break; + default: + assert (0); + abort (); } if (!cp) continue; @@ -799,144 +799,42 @@ recode_trns_proc (struct trns_header * t, struct ccase * c) if ((v->flags & RCD_DEST_MASK) == RCD_DEST_NUMERIC) { double val = cp->t.f; + double *out = &case_data_rw (c, v->dest->fv)->f; if (val == -SYSMIS) - c->data[v->dest->fv].f = c->data[v->src->fv].f; + *out = case_num (c, v->src->fv); else - c->data[v->dest->fv].f = val; + *out = val; } else { char *val = cp->t.c; - if (val == NULL) - st_bare_pad_len_copy (c->data[v->dest->fv].s, - c->data[v->src->fv].c, - v->dest->width, v->src->width); + if (val == NULL) + { + if (v->dest->fv != v->src->fv) + st_bare_pad_len_copy (case_data_rw (c, v->dest->fv)->s, + case_str (c, v->src->fv), + v->dest->width, v->src->width); + } else - memcpy (c->data[v->dest->fv].s, cp->t.c, v->dest->width); + memcpy (case_data_rw (c, v->dest->fv)->s, cp->t.c, v->dest->width); } } return -1; } - -/* Debug output. */ - -#if DEBUGGING -static void -dump_dest (struct rcd_var * v, union value * c) -{ - if ((v->flags & RCD_DEST_MASK) == RCD_DEST_NUMERIC) - if (c->f == SYSMIS) - printf ("=SYSMIS"); - else if (c->f == -SYSMIS) - printf ("=COPY"); - else - printf ("=%g", c->f); - else if (c->c) - printf ("=\"%s\"", c->c); - else - printf ("=COPY"); -} - -static void -debug_print (struct rcd_var * head) -{ - struct rcd_var *iter, *start; - struct coding *c; - - printf ("RECODE\n"); - for (iter = head; iter; iter = iter->next) - { - start = iter; - printf (" %s%s", iter == head ? "" : "/", iter->src->name); - while (iter->next && (iter->next->flags & RCD_MISC_DUPLICATE)) - { - iter = iter->next; - printf (" %s", iter->src->name); - } - if (iter->has_sysmis) - { - printf ("(SYSMIS"); - dump_dest (iter, &iter->sysmis); - printf (")"); - } - for (c = iter->map; c->type != RCD_END; c++) - { - printf ("("); - if ((iter->flags & RCD_SRC_MASK) == RCD_SRC_NUMERIC) - switch (c->type) - { - case RCD_END: - printf (_("!!END!!")); - break; - case RCD_USER: - printf ("MISSING"); - break; - case RCD_SINGLE: - printf ("%g", c->f1.f); - break; - case RCD_HIGH: - printf ("%g THRU HIGH", c->f1.f); - break; - case RCD_LOW: - printf ("LOW THRU %g", c->f1.f); - break; - case RCD_RANGE: - printf ("%g THRU %g", c->f1.f, c->f2.f); - break; - case RCD_ELSE: - printf ("ELSE"); - break; - default: - printf (_("!!ERROR!!")); - break; - } - else - switch (c->type) - { - case RCD_SINGLE: - printf ("\"%s\"", c->f1.c); - break; - case RCD_ELSE: - printf ("ELSE"); - break; - case RCD_CONVERT: - printf ("CONVERT"); - break; - default: - printf (_("!!ERROR!!")); - break; - } - if (c->type != RCD_CONVERT) - dump_dest (iter, &c->t); - printf (")"); - } - printf ("\n INTO"); - for (;;) - { - printf (" %s", - start->dest_name[0] ? start->dest_name : start->dest->name); - if (start == iter) - break; - start = start->next; - } - printf ("\n"); - } -} -#endif /* Convert NPTR to a `long int' in base 10. Returns the long int on 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 -string_to_long (char *nptr, int width, char **endptr) +static long int +string_to_long (const char *nptr, int width, const char **endptr) { int negative; register unsigned long int cutoff; register unsigned int cutlim; register unsigned long int i; - register char *s; + register const char *s; register unsigned char c; const char *save; @@ -1006,7 +904,7 @@ string_to_long (char *nptr, int width, char **endptr) found, or -SYSMIS if there was no valid number in s. WIDTH is the length of string S. From the GNU C library. */ static double -convert_to_double (char *s, int width) +convert_to_double (const char *s, int width) { register const char *end = &s[width];