X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flibpspp%2Fstr.c;h=f054c9ef28833046760957f2de9aabc7da6ec8dc;hb=03e9ea4ed60c790091ab1ea85fffa29f0965f83e;hp=b169f0d7613ee556e7a5a32e746a36ac2f06af23;hpb=c725a4f64718ef1ee4139c27c94b2eb6447b51b4;p=pspp-builds.git diff --git a/src/libpspp/str.c b/src/libpspp/str.c index b169f0d7..f054c9ef 100644 --- a/src/libpspp/str.c +++ b/src/libpspp/str.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2006, 2009 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 published by @@ -194,15 +194,18 @@ buf_copy_rpad (char *dst, size_t dst_size, void str_copy_rpad (char *dst, size_t dst_size, const char *src) { - size_t src_len = strlen (src); - if (src_len < dst_size - 1) + if (dst_size > 0) { - memcpy (dst, src, src_len); - memset (&dst[src_len], ' ', dst_size - 1 - src_len); + size_t src_len = strlen (src); + if (src_len < dst_size - 1) + { + memcpy (dst, src, src_len); + memset (&dst[src_len], ' ', dst_size - 1 - src_len); + } + else + memcpy (dst, src, dst_size - 1); + dst[dst_size - 1] = 0; } - else - memcpy (dst, src, dst_size - 1); - dst[dst_size - 1] = 0; } /* Copies SRC to DST, which is in a buffer DST_SIZE bytes long. @@ -546,6 +549,23 @@ ss_match_char (struct substring *ss, char c) return false; } +/* If the first character in SS is in MATCH, removes it and + returns the character that was removed. + Otherwise, returns EOF without changing the string. */ +int +ss_match_char_in (struct substring *ss, struct substring match) +{ + int c = EOF; + if (ss->length > 0 + && memchr (match.string, ss->string[0], match.length) != NULL) + { + c = ss->string[0]; + ss->string++; + ss->length--; + } + return c; +} + /* If SS begins with TARGET, removes it and returns true. Otherwise, returns false without changing SS. */ bool @@ -1170,31 +1190,42 @@ ds_cstr (const struct string *st_) return st->ss.string; } -/* Appends to ST a newline-terminated line read from STREAM. - Newline is the last character of ST on return, unless an I/O error - or end of file is encountered after reading some characters. - Returns true if a line is successfully read, false if no characters at - all were read before an I/O error or end of file was - encountered. */ +/* Reads characters from STREAM and appends them to ST, stopping + after MAX_LENGTH characters, after appending a newline, or + after an I/O error or end of file was encountered, whichever + comes first. Returns true if at least one character was added + to ST, false if no characters were read before an I/O error or + end of file (or if MAX_LENGTH was 0). + + This function accepts LF, CR LF, and CR sequences as new-line, + and translates each of them to a single '\n' new-line + character in ST. */ bool -ds_read_line (struct string *st, FILE *stream) +ds_read_line (struct string *st, FILE *stream, size_t max_length) { - int c; - - c = getc (stream); - if (c == EOF) - return false; + size_t length; - for (;;) + for (length = 0; length < max_length; length++) { + int c = getc (stream); + if (c == EOF) + break; + + if (c == '\r') + { + c = getc (stream); + if (c != '\n') + { + ungetc (c, stream); + c = '\n'; + } + } ds_put_char (st, c); if (c == '\n') - return true; - - c = getc (stream); - if (c == EOF) - return true; + return true; } + + return length > 0; } /* Removes a comment introduced by `#' from ST, @@ -1240,7 +1271,7 @@ ds_read_config_line (struct string *st, int *line_number, FILE *stream) ds_clear (st); do { - if (!ds_read_line (st, stream)) + if (!ds_read_line (st, stream, SIZE_MAX)) return false; (*line_number)++; ds_rtrim (st, ss_cstr (CC_SPACES));