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 "error.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 "gettext.h"
+#define _(msgid) gettext (msgid)
\f
/* Definitions. */
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). */
struct coding *map; /* Coding for other values. */
- int nmap, mmap; /* Length of map, max capacity of map. */
+ size_t nmap, mmap; /* Length of map, max capacity of map. */
};
/* RECODE transformation. */
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);
+static double convert_to_double (const char *, int);
\f
/* Parser. */
int
cmd_recode (void)
{
- int i;
+ size_t i;
/* Transformation that we're constructing. */
struct rcd_var *rcd;
/* Variables in the current part of the recoding. */
struct variable **v;
- int nv;
+ size_t nv;
/* Parses each specification between slashes. */
head = rcd = xmalloc (sizeof *rcd);
for (;;)
{
/* Get the input value (before the `='). */
- int mark = rcd->nmap;
+ size_t mark = rcd->nmap;
int code = parse_src_spec (rcd, type, max_src_width);
if (!code)
goto lossage;
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);
}
}
if (lex_match_id ("INTO"))
{
char **names;
- int nnames;
+ size_t nnames;
int success = 0;
for (i = 0; i < nnames; i++)
free (names[i]);
free (names);
- msg (SE, _("%d variable(s) cannot be recoded into "
- "%d variable(s). Specify the same number "
+ msg (SE, _("%u variable(s) cannot be recoded into "
+ "%u variable(s). Specify the same number "
"of variables as input and output variables."),
- nv, nnames);
+ (unsigned) nv, (unsigned) nnames);
goto lossage;
}
if (!v)
{
msg (SE, _("There is no string variable named "
- "%s. (All string variables specified "
- "on INTO must already exist. Use the "
- "STRING command to create a string "
- "variable.)"), names[i]);
+ "%s. (All string variables specified "
+ "on INTO must already exist. Use the "
+ "STRING command to create a string "
+ "variable.)"),
+ names[i]);
goto INTO_fail;
}
if (v->type != ALPHA)
{
msg (SE, _("Type mismatch between input and output "
- "variables. Output variable %s is not "
- "a string variable, but all the input "
- "variables are string variables."), v->name);
+ "variables. Output variable %s is not "
+ "a string variable, but all the input "
+ "variables are string variables."),
+ v->name);
goto INTO_fail;
}
if (v->width > (int) max_dst_width)
/* The NULL is only really necessary for the
debugging code. */
char *repl = xmalloc (max_dst_width + 1);
- st_pad_copy (repl, cp->t.c, max_dst_width + 1);
+ str_copy_rpad (repl, max_dst_width + 1, cp->t.c);
free (cp->t.c);
cp->t.c = repl;
}
}
+ free (v);
+ v = NULL;
+
if (!lex_match ('/'))
break;
while (rcd->next)
rcd = rcd->next;
rcd = rcd->next = xmalloc (sizeof *rcd);
-
- free (v);
- v = NULL;
}
if (token != '.')
rcd->dest = dict_create_var (default_dict, rcd->dest_name, 0);
if (!rcd->dest)
{
- /* FIXME: This can occur if a destname is duplicated.
+ /* FIXME: This can fail 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);
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);
+ str_copy_rpad (v->c, max + 1, ds_c_str (&tokstr));
flags = RCD_DEST_STRING;
*max_dst_width = max;
lex_get ();
for (;;)
{
- if (rcd->nmap >= rcd->mmap - 1)
+ if (rcd->nmap + 1 >= rcd->mmap)
{
rcd->mmap += 16;
- rcd->map = xrealloc (rcd->map, rcd->mmap * sizeof *rcd->map);
+ rcd->map = xnrealloc (rcd->map, rcd->mmap, sizeof *rcd->map);
}
c = &rcd->map[rcd->nmap];
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);
+ str_copy_rpad (c->f1.c, max_src_width + 1, ds_c_str (&tokstr));
lex_get ();
}
}
static void
recode_trns_free (struct trns_header * t)
{
- int i;
+ size_t i;
struct rcd_var *head, *next;
head = ((struct recode_trns *) t)->codings;
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;
case RCD_END:
return NULL;
case RCD_USER:
- if (is_num_user_missing (cmp, v->src))
+ if (mv_is_num_user_missing (&v->src->miss, cmp))
return cp;
break;
case RCD_SINGLE:
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;
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)
+ buf_copy_rpad (case_data_rw (c, v->dest->fv)->s,
+ v->dest->width,
+ case_str (c, v->src->fv), 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);
}
}
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 unsigned char c;
+ unsigned long int cutoff;
+ unsigned int cutlim;
+ unsigned long int i;
+ const char *s;
+ unsigned char c;
const char *save;
s = nptr;
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];
+ const char *end = &s[width];
short int sign;