/*
* parser.c - simple line based parser
*
* Copyright (C) 2006, 2007 Olaf Kirch <olaf.kirch@oracle.com>
*/
#include <stdlib.h>
#include <getopt.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <err.h>
#include <libisns/util.h>
/*
* By default, the parser will recognize any white space
* as "word" separators.
* If you need additional separators, you can put them
* here.
*/
const char * parser_separators = NULL;
const char * parser_punctuation = "=";
char *
parser_get_next_line(FILE *fp)
{
static char buffer[8192];
unsigned int n = 0, count = 0;
int c, continuation = 0;
while (n < sizeof(buffer) - 1) {
c = fgetc(fp);
if (c == EOF)
break;
count++;
if (c == '\r')
continue;
/* Discard all blanks
* following a backslash-newline
*/
if (continuation) {
if (c == ' ' || c == '\t')
continue;
continuation = 0;
}
if (c == '\n') {
if (n && buffer[n-1] == '\\') {
buffer[--n] = '\0';
continuation = 1;
}
while (n && isspace(buffer[n-1]))
buffer[--n] = '\0';
if (!continuation)
break;
buffer[n++] = ' ';
continue;
}
buffer[n++] = c;
}
if (count == 0)
return NULL;
buffer[n] = '\0';
return buffer;
}
static inline int
is_separator(char c)
{
if (isspace(c))
return 1;
return parser_separators && c && strchr(parser_separators, c);
}
static inline int
is_punctuation(char c)
{
return parser_punctuation && c && strchr(parser_punctuation, c);
}
char *
parser_get_next_word(char **sp)
{
static char buffer[512];
char *s = *sp, *p = buffer;
while (is_separator(*s))
++s;
if (*s == '\0')
goto done;
if (is_punctuation(*s)) {
*p++ = *s++;
goto done;
}
while (*s && !is_separator(*s) && !is_punctuation(*s))
*p++ = *s++;
done:
*p++ = '\0';
*sp = s;
return buffer[0]? buffer : NULL;
}
int
parser_split_line(char *line, unsigned int argsmax, char **argv)
{
unsigned int argc = 0;
char *s;
while (argc < argsmax && (s = parser_get_next_word(&line)))
argv[argc++] = strdup(s);
return argc;
}
char *
parser_get_rest_of_line(char **sp)
{
char *s = *sp, *res = NULL;
while (is_separator(*s))
++s;
*sp = "";
if (*s != '\0')
res = s;
return res;
}