shithub: svcfs

ref: b5aa12ceca7ee1532a457189b8e304c59e15f711
dir: /convS2C.c/

View raw version
#include <u.h>
#include <libc.h>
#include <fcall.h>
#include <thread.h>
#include <9p.h>
#include "alt.h"

struct state
{
	Cmd cmd;
	char *base;
	int size;
	int (*fn)(struct state *s);	
};

static int parse_cmd(struct state *s);
static int parse_from(struct state *s);
static int parse_data(struct state *s);

uint
convS2C(Cmd *cmd, char *c, uint n)
{
	struct state s;

	s.fn = (*parse_cmd);
	s.cmd.type = ErrorCmd;
	s.base = c;
	s.size = n;
	while((s.fn(&s) > 0));

	cmd->type = s.cmd.type;
	cmd->data = s.cmd.data;
	strcpy(cmd->buffer, s.cmd.buffer);
	strcpy(cmd->svccmd, s.cmd.svccmd);
	return sizeof(cmd);
}

static int
parse_cmd(struct state *s)
{
	int n;
	char *first;

	n = 0;
	for(;;){
		if(n > s->size)
			return -1;
		switch(s->base[n]){
		case '\0':
		case '\r':
		case '\n':
			// Check we aren't at "quit"
			s->base[n] = '\0';
			s->cmd.type = CloneCmd;
			if(strncmp("quit", s->base, n) == 0)
				s->cmd.type = QuitCmd;
			else
				s->cmd.data = strdup(s->base);
			return 0;
		case ' ':
		case '\t':
			// The overwhelming majority will be feed activity
			if(strncmp(s->base, "feed", 4) == 0)
				s->cmd.type = FeedCmd;
			else if(strncmp(s->base, "asi", 3) == 0)
				s->cmd.type = SideCmd;
			else if(strncmp(s->base, "nav", 3) == 0)
				s->cmd.type = NavCmd;
			else if(strncmp(s->base, "titl", 4) == 0)
				s->cmd.type = TitleCmd;
			else if(strncmp(s->base, "ima", 3) == 0)
				s->cmd.type = ImageCmd;
			else if(strncmp(s->base, "del", 3) == 0)
				s->cmd.type = DeleteCmd;
			else if(strncmp(s->base, "rem", 3) == 0)
				s->cmd.type = RemoveCmd;
			else if(strncmp(s->base, "noti", 4) == 0)
				s->cmd.type = NotifyCmd;
			else if(strncmp(s->base, "err", 3) == 0)
				s->cmd.type = ErrorCmd;
			else if(strncmp(s->base, "stat", 4) == 0)
				s->cmd.type = StatusCmd;
			else if(strncmp(s->base, "crea", 4) == 0)
				s->cmd.type = CreateCmd;
			else if(strncmp(s->base, "buf", 3) == 0)
				s->cmd.type = BufferCmd;
			else if(strncmp(s->base, "mark", 4) == 0)
				s->cmd.type = MarkdownCmd;
			else {
				s->cmd.type = ServiceCmd;
				first = strtok(s->base, " ");
				sprint(s->cmd.svccmd, first);
			}
			s->size -= n;
			n++;
			s->base += n;
			s->fn = (*parse_from);
			return 1;
		default:
			n++;
		}
	}
}

static int
parse_from(struct state *s)
{
	int n;
	n = 0;
	for(;;){
		if(n > s->size || n > MaxBuflen)
			return -1;
		switch(s->base[n]){
		// leading spaces/tabs, ignore
		case ' ':
		case '\t':
			// NOTE: This moves our pointer forward so n++ isn't necessary
			s->size--;
			s->base++;
			break;
		case '\0':
			strncpy(s->cmd.buffer, s->base, n);
			return 0;
		case '\n':
		case '\r':
			s->base[n] = '\0';
			strncpy(s->cmd.buffer, s->base, n+1);
			// return if we have no data to parse
			if (n >= s->size)
				return 0;
			s->size -=n;
			n++;
			s->base += n;
			s->fn = (*parse_data);
			return 1;
		default:
			n++;
		}
	}
}

static int
parse_data(struct state *s)
{
	// We may eventually do some processing here
	s->cmd.data = strdup(s->base);
	return 0;
}