X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=perl-module%2FPSPP.xs;h=15d3b606cbecdab2aa76ae5324b347cc094e55fa;hb=3da49359c52cb783db907cc197847bbd5e721c97;hp=237ae95f541a9564829ff93bff2ce33d8fcb2314;hpb=8953baa61127d6d3b91f763663ea647bf3e4e793;p=pspp diff --git a/perl-module/PSPP.xs b/perl-module/PSPP.xs index 237ae95f54..15d3b606cb 100644 --- a/perl-module/PSPP.xs +++ b/perl-module/PSPP.xs @@ -1,5 +1,5 @@ /* PSPP - computes sample statistics. - Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc. + Copyright (C) 2007, 2008, 2009, 2010 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 @@ -17,12 +17,18 @@ 02110-1301, USA. */ +#include + +/* The Gnulib "strftime" module defines my_strftime in for use by + gl/strftime.c. Perl also defines my_strftime in embed.h for some other + purpose. The former definition doesn't matter in this file, so suppress it + to avoid a compiler warning. */ +#undef my_strftime + #include "EXTERN.h" #include "perl.h" #include "XSUB.h" -#include - #include "ppport.h" #include "minmax.h" @@ -38,9 +44,11 @@ #include #include #include +#include #include #include #include +#include #include typedef struct fmt_spec input_format ; @@ -113,8 +121,9 @@ scalar_to_value (union value *val, SV *scalar, const struct variable *var) { STRLEN len; const char *p = SvPV (scalar, len); - memset (val->s, ' ', var_get_width (var)); - memcpy (val->s, p, len); + int width = var_get_width (var); + value_set_missing (val, width); + memcpy (value_str_rw (val, width), p, len); } } @@ -130,7 +139,10 @@ value_to_scalar (const union value *val, const struct variable *var) return newSVnv (val->f); } else - return newSVpvn (val->s, var_get_width (var)); + { + int width = var_get_width (var); + return newSVpvn (value_str (val, width), width); + } } @@ -142,12 +154,11 @@ var_set_input_format (struct variable *v, input_format ip_fmt) var_attach_aux (v, if_copy, var_dtor_free); } -static union value * -make_value_from_scalar (SV *val, const struct variable *var) +static void +make_value_from_scalar (union value *uv, SV *val, const struct variable *var) { - union value *uv = value_create (var_get_width (var)); + value_init (uv, var_get_width (var)); scalar_to_value (uv, val, var); - return uv; } @@ -159,7 +170,12 @@ void onBoot (ver) const char *ver CODE: - assert (0 == strcmp (ver, bare_version)); + /* Check that the version is correct up to the length of 'ver'. + This allows PSPP autobuilders to add a "-build#" suffix to the + PSPP version without causing failures here. */ + assert (0 == strncmp (ver, bare_version, strlen (ver))); + + i18n_init (); msg_init (NULL, message_handler); settings_init (0, 0); fh_init (); @@ -171,12 +187,11 @@ format_value (val, var) CODE: SV *ret; const struct fmt_spec *fmt = var_get_print_format (var); - union value *uv = make_value_from_scalar (val, var); + union value uv; char *s; - s = malloc (fmt->w); - memset (s, '\0', fmt->w); - data_out (uv, fmt, s); - free (uv); + make_value_from_scalar (&uv, val, var); + s = data_out (&uv, var_get_encoding (var), fmt); + value_destroy (&uv, var_get_width (var)); ret = newSVpv (s, fmt->w); free (s); RETVAL = ret; @@ -189,9 +204,11 @@ value_is_missing (val, var) SV *val struct variable *var CODE: - union value *uv = make_value_from_scalar (val, var); - int ret = var_is_value_missing (var, uv, MV_ANY); - free (uv); + union value uv; + int ret; + make_value_from_scalar (&uv, val, var); + ret = var_is_value_missing (var, &uv, MV_ANY); + value_destroy (&uv, var_get_width (var)); RETVAL = ret; OUTPUT: RETVAL @@ -365,6 +382,37 @@ clear_value_labels (var) CODE: var_clear_value_labels (var); +SV * +get_write_format (var) + struct variable *var +CODE: + HV *fmthash = (HV *) sv_2mortal ((SV *) newHV()); + const struct fmt_spec *fmt = var_get_write_format (var); + + hv_store (fmthash, "fmt", 3, newSVnv (fmt->type), 0); + hv_store (fmthash, "decimals", 8, newSVnv (fmt->d), 0); + hv_store (fmthash, "width", 5, newSVnv (fmt->w), 0); + + RETVAL = newRV ((SV *) fmthash); + OUTPUT: +RETVAL + +SV * +get_print_format (var) + struct variable *var +CODE: + HV *fmthash = (HV *) sv_2mortal ((SV *) newHV()); + const struct fmt_spec *fmt = var_get_print_format (var); + + hv_store (fmthash, "fmt", 3, newSVnv (fmt->type), 0); + hv_store (fmthash, "decimals", 8, newSVnv (fmt->d), 0); + hv_store (fmthash, "width", 5, newSVnv (fmt->w), 0); + + RETVAL = newRV ((SV *) fmthash); + OUTPUT: +RETVAL + + void pxs_set_write_format (var, fmt) struct variable *var @@ -398,26 +446,27 @@ INIT: sv_setpv (errstr, ""); CODE: union value the_value; + int width = var_get_width (var); + int ok; + value_init (&the_value, width); if ( var_is_numeric (var)) { if ( ! looks_like_number (key)) { sv_setpv (errstr, "Cannot add label with string key to a numeric variable"); + value_destroy (&the_value, width); XSRETURN_IV (0); } the_value.f = SvNV (key); } else { - if ( var_is_long_string (var) ) - { - sv_setpv (errstr, "Cannot add label to a long string variable"); - XSRETURN_IV (0); - } - strncpy (the_value.s, SvPV_nolen(key), MAX_SHORT_STRING); + value_copy_str_rpad (&the_value, width, SvPV_nolen(key), ' '); } - if (! var_add_value_label (var, &the_value, label) ) + ok = var_add_value_label (var, &the_value, label); + value_destroy (&the_value, width); + if (!ok) { sv_setpv (errstr, "Something went wrong"); XSRETURN_IV (0); @@ -486,20 +535,20 @@ get_value_labels (var) struct variable *var CODE: HV *labelhash = (HV *) sv_2mortal ((SV *) newHV()); - struct val_lab *vl; + const struct val_lab *vl; struct val_labs_iterator *viter = NULL; const struct val_labs *labels = var_get_value_labels (var); if ( labels ) { - for (vl = val_labs_first (labels, &viter); + for (vl = val_labs_first (labels); vl; - vl = val_labs_next (labels, &viter)) + vl = val_labs_next (labels, vl)) { SV *sv = value_to_scalar (&vl->value, var); STRLEN len; const char *s = SvPV (sv, len); - hv_store (labelhash, s, len, newSVpv (vl->label, 0), 0); + hv_store (labelhash, s, len, newSVpv (val_lab_get_label (vl), 0), 0); } } @@ -540,6 +589,7 @@ CODE: struct file_handle *fh = fh_create_file (NULL, name, fh_default_properties () ); struct sysfile_info *sfi = xmalloc (sizeof (*sfi)); + dict_set_encoding (dict, "UTF-8"); sfi->writer = sfm_open_writer (fh, dict, opts); sfi->dict = dict; sfi->opened = true; @@ -589,7 +639,7 @@ CODE: if ( av_len (av_case) >= dict_get_var_cnt (sfi->dict)) XSRETURN_UNDEF; - c = case_create (dict_get_next_value_idx (sfi->dict)); + c = case_create (dict_get_proto (sfi->dict)); dict_get_vars (sfi->dict, &vv, &nv, 1u << DC_ORDINARY | 1u << DC_SYSTEM); @@ -604,9 +654,16 @@ CODE: if ( ifmt ) { struct substring ss = ss_cstr (SvPV_nolen (sv)); - if ( ! data_in (ss, LEGACY_NATIVE, ifmt->type, 0, 0, 0, - case_data_rw (c, v), - var_get_width (v)) ) + char *error; + bool ok; + + error = data_in (ss, LEGACY_NATIVE, ifmt->type, + case_data_rw (c, v), var_get_width (v), + dict_get_encoding (sfi->dict)); + ok = error == NULL; + free (error); + + if ( !ok ) { RETVAL = 0; goto finish; @@ -623,10 +680,7 @@ CODE: { const struct variable *v = vv[i++]; union value *val = case_data_rw (c, v); - if ( var_is_numeric (v)) - val->f = SYSMIS; - else - memset (val->s, ' ', var_get_width (v)); + value_set_missing (val, var_get_width (v)); } RETVAL = casewriter_write (sfi->writer, c); finish: