shithub: spread

ref: eaadfa055fc6b9e7074449a8ad6b0a4ff25cb346
dir: /preproc.c/

View raw version
#include <u.h>
#include <libc.h>
#include <regexp.h>
#include <String.h>
#include "spread.h"

Reprog *rrange = nil;

/* begin test code */
/* acid:
 * acid: new()
 * acid: *PC=testpreproc
 * acid: cont()
 */
void
t(char *s)
{
	Cell c;
	
	c.procvalue = nil;
	c.value = strdup(s);
	preprocess(&c);
	fprint(2, "'%s' → '%s'\n", s, c.procvalue);
	free(c.value);
}

void
testpreproc(void)
{
	t("A1()+[A1()/B4()]+A5()");
	t("A1()+[A1()+B4()]+A5()");
	t("A1()+[A1()-B4()]+A5()");
	t("A1()+[A1()*B4()]+A5()");
	exits(nil);
}
/* end test code */

void
appendrange(String *s, char sign, P a, P b)
{
	int x, y;
	P na, nb;
	P p;
	char *ps;
	int first;
	
	na.x = a.x < b.x ? a.x : b.x;
	na.y = a.y < b.y ? a.y : b.y;
	nb.x = a.x > b.x ? a.x : b.x;
	nb.y = a.y > b.y ? a.y : b.y;
	
	first = 1;
	s_putc(s, '(');
	for (x = na.x; x <= nb.x; x++)
		for (y = na.y; y <= nb.y; y++) {
			p.x = x;
			p.y = y;
			ps = ptoa(p);
			if (!first)
				s_putc(s, sign);
			first = 0;
			s_append(s, ps);
			s_append(s, "()");
		}
	s_putc(s, ')');
}

int
prange(Cell *c)
{
	Resub match[4];
	char *s;
	String *str;
	P a, b;
	char sign;
	
	if (!rrange)
		rrange = regcomp("\\[([A-Z]+[0-9]+\\(\\))([+\\-*/])([A-Z]+[0-9]+\\(\\))\\]");
	assert(rrange);
	
	memset(match, 0, 4*sizeof(Resub));
	
	s = c->procvalue ? c->procvalue : c->value;
	str = nil;
	
	while (regexec(rrange, s, match, 4)) {
		if (!str)
			str = s_new();
		
		s_nappend(str, s, match[0].sp-s);
		
		s = match[0].ep;
		sign = *match[2].sp;
		a = atop(match[1].sp);
		b = atop(match[3].sp);
		
		appendrange(str, sign, a, b);
		match[0].sp = nil;
		match[0].ep = nil;
	}
	
	if (str) {
		s_append(str, s);
		c->procvalue = strdup(s_to_c(str));
		s_free(str);
	} else
		c->procvalue = c->value;
	
	return 1;
}

int
preprocess(Cell *c)
{
	int r = 0;
	
	if (!prange(c))
		r++;
	
	return !r;
}