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 <config.h>
-#include <assert.h>
+#include "error.h"
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include "alloc.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"
\f
/* Definitions. */
+/* Type of source value for RECODE. */
enum
{
RCD_END, /* sentinel value */
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). */
static int parse_src_spec (struct rcd_var * rcd, int type, size_t max_src_width);
static trns_proc_func recode_trns_proc;
static trns_free_func recode_trns_free;
-static double convert_to_double (char *, int);
-
-#if DEBUGGING
-static void debug_print (struct rcd_var * head);
-#endif
+static double convert_to_double (const char *, int);
\f
/* 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)
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. */
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);
}
}
}
+ free (v);
+ v = NULL;
+
if (!lex_match ('/'))
break;
while (rcd->next)
rcd = rcd->next;
rcd = rcd->next = xmalloc (sizeof *rcd);
-
- free (v);
}
if (token != '.')
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;
v->c = NULL;
- if (token == T_NUM)
+ if (lex_is_number ())
{
v->f = tokval;
lex_get ();
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 ();
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;
return 0;
}
}
- else if (token == T_NUM)
+ else if (lex_is_number ())
{
c->f1.f = tokval;
lex_get ();
{
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;
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 ();
}
}
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)
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;
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;
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;
static int
recode_trns_proc (struct trns_header * t, struct ccase * c,
- int case_num UNUSED)
+ int case_idx UNUSED)
{
struct rcd_var *v;
break;
default:
assert (0);
+ abort ();
}
if (!cp)
continue;
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;
}
-\f
-/* 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. */
static long int
-string_to_long (char *nptr, int width, char **endptr)
+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;
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];