shithub: vcardfs

ref: a0054fa2fc711277c267fbd7d6b48bff6e0d4a82
dir: /libvcard/vlex.c/

View raw version
#include <u.h>
#include <libc.h>
#include "vcard.h"
#include "y.tab.h"

//#define DEBUG

static void
iltolower(char *s)
{
	while (*s) {
		if (*s >= 'A' && *s <= 'Z')
			*s = *s - 'A' + 'a';
		s++;
	}
}

char *vcparsestr;
Vstate vcstate;

static char beginstr[] = "begin:vcard\r\n";
static char endstr[] = "end:vcard";

static char verbchars[] = ":;\"=";

int
yylex(void)
{
	int n;
	char *s, *t;
	
	if (!vcstate.s) {
		vcstate.s = vcstate.str;
	}
	
#ifdef DEBUG
	fprint(2, "vcstate:\n"
		"  str: %p\n"
		"  s: %c\n"
		"  invalue: %d\n"
		"  inquote: %d\n"
		"  haspropname: %d\n",
		vcstate.str, *vcstate.s, vcstate.invalue, vcstate.inquote, vcstate.haspropname);
#endif
	
	
	/* value string */
	if (vcstate.invalue) {
		s = strstr(vcstate.s, "\r\n");
		if (!s) {
			yylval.s = strdup(vcstate.s);
			vcstate.s = strchr(vcstate.s, 0);
			return FWORD;
		}
		yylval.s = mallocz(s - vcstate.s + 1, 1);
		memcpy(yylval.s, vcstate.s, s - vcstate.s);
		vcstate.s = s;
		vcstate.invalue = 0;
		vcstate.haspropname = 0;
#ifdef DEBUG
		fprint(2, "  FWORD: %s\n", yylval.s);
#endif
		return FWORD;
	}
	
	/* quoted string */
	if (vcstate.inquote == 1) {
		s = strchr(vcstate.s, '"');
		if (!s) {
			fprint(2, "parse error: quotes not closing!\n");
			return -1;
		}
		yylval.s = mallocz(s - vcstate.s + 1, 1);
		memcpy(yylval.s, vcstate.s, s - vcstate.s);
		vcstate.s = s;
		vcstate.inquote = 2;
#ifdef DEBUG
		fprint(2, "  FWORD: %s\n", yylval.s);
#endif
		return FWORD;
	}
	
	/* verbatim characters */
	if (strchr(verbchars, *vcstate.s)) {
		switch (*vcstate.s) {
		case ':':
			vcstate.invalue++;
			break;
		case '"':
			if (vcstate.inquote == 2) {
				vcstate.inquote = 0;
			} else {
				vcstate.inquote++;
			}
			break;
		}
		n = *vcstate.s;
		vcstate.s++;
#ifdef DEBUG
		fprint(2, "  VERBCHAR: '%c'\n", n);
#endif
		return n;
	}
	
	/* newline */
	if (cistrncmp(vcstate.s, "\r\n", 2) == 0) {
		vcstate.s += 2;
		/* collapse multiple crlf sequences */
		while (cistrncmp(vcstate.s, "\r\n", 2) == 0) {
			vcstate.s += 2;
		}
#ifdef DEBUG
		fprint(2, "  CRLF\n");
#endif
		return CRLF;
	}
	
	/* begin block */
	n = strlen(beginstr);
	if (cistrncmp(vcstate.s, beginstr, n) == 0) {
		vcstate.s += n;
#ifdef DEBUG
		fprint(2, "  BEGIN\n");
#endif
		return BEGIN;
	}
	
	/* end block */
	n = strlen(endstr);
	if (cistrncmp(vcstate.s, endstr, n) == 0) {
		vcstate.s += n;
#ifdef DEBUG
		fprint(2, "  END\n");
#endif
		return END;
	}
	
	/* assume SWORD string (unquoted param value or param name) */
	s = strchr(vcstate.s, ':');
	t = strchr(vcstate.s, ';');
	if (t)
		s = s < t ? s : t;
	t = strchr(vcstate.s, '=');
	if (t)
		s = s < t ? s : t;
	n = s - vcstate.s;
	yylval.s = mallocz(n + 1, 1);
	memcpy(yylval.s, vcstate.s, n);
	vcstate.s += n;
#ifdef DEBUG
	fprint(2, "  SWORD: %s\n", yylval.s);
#endif
	return SWORD;
}