X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fvariable.c;h=ee6c8747865b734cf0ba0f2eb00bdd543a39040c;hb=2766c2d47448010527d52dd304213d0bb563dd00;hp=78f0cb443acf2387e5cad42fa07444b71212c2ee;hpb=a19b858e0ac3c69e4a28c0ca6d8674427268a863;p=pspp-builds.git diff --git a/src/data/variable.c b/src/data/variable.c index 78f0cb44..ee6c8747 100644 --- a/src/data/variable.c +++ b/src/data/variable.c @@ -131,26 +131,33 @@ hash_value(const union value *v, int width) bool var_is_valid_name (const char *name, bool issue_error) { + bool plausible; size_t length, i; assert (name != NULL); + /* Note that strlen returns number of BYTES, not the number of + CHARACTERS */ length = strlen (name); - if (length < 1) - { - if (issue_error) - msg (SE, _("Variable name cannot be empty string.")); - return false; - } - else if (length > LONG_NAME_LEN) + + plausible = var_is_plausible_name(name, issue_error); + + if ( ! plausible ) + return false; + + + if (!lex_is_id1 (name[0])) { if (issue_error) - msg (SE, _("Variable name %s exceeds %d-character limit."), - name, (int) LONG_NAME_LEN); + msg (SE, _("Character `%c' (in %s), may not appear " + "as the first character in a variable name."), + name[0], name); return false; } + for (i = 0; i < length; i++) + { if (!lex_is_idn (name[i])) { if (issue_error) @@ -159,13 +166,38 @@ var_is_valid_name (const char *name, bool issue_error) name[i], name); return false; } - - if (!lex_is_id1 (name[0])) + } + + return true; +} + +/* + Returns true if NAME is an plausible name for a variable, + false otherwise. If ISSUE_ERROR is true, issues an + explanatory error message on failure. + This function makes no use of LC_CTYPE. +*/ +bool +var_is_plausible_name (const char *name, bool issue_error) +{ + size_t length; + + assert (name != NULL); + + /* Note that strlen returns number of BYTES, not the number of + CHARACTERS */ + length = strlen (name); + if (length < 1) { if (issue_error) - msg (SE, _("Character `%c' (in %s), may not appear " - "as the first character in a variable name."), - name[0], name); + msg (SE, _("Variable name cannot be empty string.")); + return false; + } + else if (length > LONG_NAME_LEN) + { + if (issue_error) + msg (SE, _("Variable name %s exceeds %d-character limit."), + name, (int) LONG_NAME_LEN); return false; } @@ -228,7 +260,7 @@ void var_set_short_name (struct variable *v, const char *short_name) { assert (v != NULL); - assert (short_name[0] == '\0' || var_is_valid_name (short_name, false)); + assert (short_name[0] == '\0' || var_is_plausible_name (short_name, false)); str_copy_trunc (v->short_name, sizeof v->short_name, short_name); str_uppercase (v->short_name); @@ -318,3 +350,111 @@ dict_class_to_name (enum dict_class dict_class) abort (); } } + + +/* Copies buffer SRC, of SRC_SIZE bytes, to DST, of DST_SIZE bytes. + Each 256th byte, which is expected to be a ' ', is deleted. + DST is then truncated to DST_SIZE bytes or padded on the right with + spaces as needed. */ +void +copy_demangle (char *dst, size_t dst_size, + const char *src, size_t src_size) +{ + int src_bytes_left = src_size; + int dst_bytes_left = dst_size; + const char *s = src; + char *d = dst; + + + while( src_bytes_left > 0 ) + { + const size_t s_chunk = min(MAX_LONG_STRING, src_bytes_left); + const size_t d_chunk = min(MAX_LONG_STRING, dst_bytes_left); + + assert ( d < dst + dst_size); + + buf_copy_rpad (d, d_chunk, + s, s_chunk); + + d += d_chunk; + s += s_chunk; + src_bytes_left -= s_chunk; + dst_bytes_left -= d_chunk; + + if ( src_bytes_left > 0 && ! (++s - src) % (MAX_LONG_STRING+1) ) + { + if ( *s != ' ') + msg(MW, _("Expected a space in very long string")); + src_bytes_left--; + } + } +} + +/* Copies buffer SRC, of SRC_SIZE bytes, to DST, of DST_SIZE bytes. + DST is rounded up to the nearest 8 byte boundary. + A space is inserted at each 256th byte. + DST is then truncated to DST_SIZE bytes or padded on the right with + spaces as needed. */ +void +copy_mangle (char *dst, size_t dst_size, + const char *src, size_t src_size) +{ + int src_bytes_left = src_size; + int dst_bytes_left = dst_size; + const char *s = src; + char *d = dst; + + memset(dst, ' ', dst_size); + + while( src_bytes_left > 0 ) + { + const size_t s_chunk = min(MAX_LONG_STRING, src_bytes_left); + const size_t d_chunk = min(MAX_LONG_STRING, dst_bytes_left); + + buf_copy_rpad (d, d_chunk, s, s_chunk); + + d += d_chunk; + s += s_chunk; + src_bytes_left -= s_chunk; + dst_bytes_left -= d_chunk; + + if ( dst_bytes_left > 0 && 0 == ( d + 1 - dst ) % (MAX_LONG_STRING + 1) ) + { + memset(d, ' ', 1); + d++; + dst_bytes_left--; + } + } +} + +/* Return the number of bytes used when writing case_data for a variable + of WIDTH */ +int +width_to_bytes(int width) +{ + const int chunks = width / EFFECTIVE_LONG_STRING_LENGTH ; + const int remainder = width - (chunks * EFFECTIVE_LONG_STRING_LENGTH) ; + int bytes, mod8; + + assert (width >= 0); + + if ( width == 0 ) + return MAX_SHORT_STRING ; + + if ( width <= MAX_LONG_STRING) + return MAX_SHORT_STRING * DIV_RND_UP(width, MAX_SHORT_STRING); + + + bytes = remainder + (chunks * (MAX_LONG_STRING + 1) ); + + /* Round up to the nearest 8 */ + mod8 = bytes % MAX_SHORT_STRING; + + if ( mod8 ) + bytes += MAX_SHORT_STRING - mod8; + + assert( bytes % MAX_SHORT_STRING == 0 ); + + return bytes; +} +