/* ioutils version 1.0 by Andrew Poelstra */ #include #include #include #include #include "ioutils.h" /* Reads from fh into buff (buff may be NULL, in which case characters * * are discarded), up until it reaches either stop_c or whitespace. (In * * the special case that the first character is a quote, it will simply * * read everything until it reaches an end quote.) Unless buff is NULL, * * it reads at most (maxlen-1) characters and null-terminates buff. If * * count is non-NULL, it will be filled with the number of characters * * read. Returns 0 on success or EOF on error. */ int gets_ws (char *buff, size_t *count, size_t maxlen, char stop_c, FILE *fh) { size_t i = 0; int err = (fh == NULL); int stop_white = 1; int ch = err ? EOF : getc (fh); int pch = ch; switch (ch) { case '\"': case '\'': case '`': stop_white = 0; stop_c = ch; break; case EOF: err = 1; } while ((!stop_white || !isspace (ch)) && (!buff || i < maxlen) && (ch != stop_c || pch == '\\')) { pch = ch; if (buff && i < maxlen) buff[i++] = ch; if (ch == EOF) { err = (ch == EOF); ch = stop_c; } else { ch = getc (fh); } ++i; } if (count != NULL) *count = i; /* We need to check in case maxlen is 0. */ if (buff && maxlen) buff[i] = 0; ungetc (ch, fh); return err ? EOF : 0; } /* Kinda obvious: skips all whitespace in stream and returns first non-white * character. (The first non-white character is put back into the stream for * further parsing.) */ int skip_white (FILE *stream) { int ch; if (!stream) return EOF; ch = getc (stream); while (ch != EOF && isspace (ch)) ch = getc (stream); ungetc (ch, stream); return ch; } /* Reads from stream lines such as * tagname "Tag value here" * allowing for unlimited whitespace and a colon at the end of tagname. */ int gets_tv (FILE *stream, char *tag_name, char *tag_value, size_t name_max, size_t value_max) { int erred = 0; if (!erred) erred = (skip_white (stream) == EOF); if (!erred) erred = gets_ws (tag_name, NULL, name_max, ':', stream); if (!erred) erred = gets_ws (NULL, NULL, 0, ':', stream); /* Flush buffer. */ if (!erred) erred = (skip_white (stream) == EOF); if (!erred) erred = gets_ws (tag_value, NULL, value_max, 0, stream); if (!erred) erred = gets_ws (NULL, NULL, 0, 0, stream); /* Flush buffer. */ return erred; } /* Warning: *nix specific function; must be rewritten for other OSes. * The Windows equivilant would return "%APPDATA%[suffix]" perhaps. * suffix should be of the form /dir/file (with a preceding slash) */ char *home_fname (char *suffix) { char *tmpptr = getenv ("HOME"); char *retptr; size_t len = suffix ? strlen (suffix) : 0; len += tmpptr ? strlen (tmpptr) : 0; retptr = malloc (len + 1); if (retptr) { if (tmpptr) strcpy (retptr, tmpptr); else *retptr = 0; if (suffix) strcat (retptr, suffix); } return retptr; }