stew

a monorepo of some sort
git clone git://git.nsmpr.xyz/stew.git
Log | Files | Refs

fltp.c (2566B)


      1 /*
      2  * Forth-Like Tree Protocol
      3  */
      4 
      5 #include <u.h>
      6 #include <libc.h>
      7 
      8 #include "fltp.h"
      9 
     10 FLTWord dict[] = {
     11 	{&dict[1], "{",    fltpstartlist},
     12 	{&dict[2], "}",    fltpendlist},
     13 	{nil,      ".n",   fltpgetline},
     14 };
     15 
     16 FLTP *
     17 initfltp(void){
     18 	FLTP *new;
     19 	new = mallocz(sizeof(FLTP), 1);
     20 	new->fp = new->rs;
     21 	*(new->fp) = fltpmain; // TODO: should be actual func
     22 	new->tbuf = malloc(FLTTokenBufSize);
     23 	new->wp = dict;
     24 	return new;
     25 }
     26 
     27 void
     28 evalfltp(FLTP *fltp, char *buf, long nbytes){
     29 	fltp->bp = buf;
     30 	fltp->nbytes = nbytes;
     31 	(*fltp->fp)(fltp);
     32 }
     33 
     34 FLTNode *
     35 createfltnode(FLTNode *prev, FLTNode *parent, char *buf, long nbytes)
     36 {
     37 	FLTNode *new;
     38 	new = malloc(sizeof(FLTNode) + nbytes);
     39 	new->prev = prev;
     40 	new->next = nil;
     41 	new->parent = parent;
     42 	new->nbytes = nbytes;
     43 	memcpy((char *)new + sizeof(FLTNode), buf, nbytes);
     44 	if(prev != nil) prev->next = new;
     45 	return new;
     46 }
     47 
     48 FLTWord *
     49 getfltword(char *str, long nbytes, FLTWord *wp)
     50 {
     51 	if(nbytes >= FLTWordSize) return nil;
     52 	for(; wp != nil; wp = wp->prev){
     53 		if(strlen(wp->str) != nbytes) continue;
     54 		if(memcmp(wp->str, str, nbytes) == 0) return wp;
     55 	}
     56 	return nil;
     57 }
     58 
     59 void
     60 fltpmain(FLTP *fltp){
     61 	FLTWord *wp;
     62 	for(;;){
     63 		fltpgettoken(fltp);
     64 		if(fltp->ti > 0){
     65 			fltp->np = createfltnode(fltp->np, fltp->pnp, fltp->tbuf, fltp->ti);
     66 			wp = getfltword(fltp->tbuf, fltp->ti, fltp->wp);
     67 			if(wp != nil) wp->fp(fltp); // TODO: should utilise fltp->rs ???
     68 		}
     69 		if(fltp->nbytes == 0) break;
     70 	}
     71 }
     72 
     73 void
     74 fltpgettoken(FLTP *fltp){
     75 	int c;
     76 	fltp->ti = 0;
     77 	for(;;){
     78 		if(fltp->ti >= FLTTokenBufSize) sysfatal("fltpgettoken: token buffer overflow");
     79 		c = *fltp->bp;
     80 		fltp->bp++;
     81 		fltp->nbytes--;
     82 		if(strchr(" \t\n", c) != nil) break;
     83 		fltp->tbuf[fltp->ti] = c;
     84 		fltp->ti++;
     85 		if(fltp->nbytes == 0) sysfatal("fltpgettoken: input buffer overflow (unterminated token)");
     86 	}
     87 }
     88 
     89 void
     90 fltpstartlist(FLTP *fltp){
     91 	fltp->pnp = fltp->np;
     92 }
     93 
     94 void
     95 fltpendlist(FLTP *fltp){
     96 	if(fltp->pnp == nil) sysfatal("fltpendlist: nil in parent pointer");
     97 	fltp->pnp = fltp->pnp->parent;
     98 }
     99 
    100 void
    101 fltpgetline(FLTP *fltp){
    102 	int c;
    103 	fltp->ti = 0;
    104 	for(;;){
    105 		if(fltp->ti >= FLTTokenBufSize) sysfatal("fltpgetline: token buffer overflow");
    106 		c = *fltp->bp;
    107 		fltp->bp++;
    108 		fltp->nbytes--;
    109 		if(c == '\n') break;
    110 		fltp->tbuf[fltp->ti] = c;
    111 		fltp->ti++;
    112 		if(fltp->nbytes == 0){
    113 			fprint(2,"tbuf: %.*s\n", fltp->ti, fltp->tbuf);
    114 			sysfatal("fltpgetline: input buffer overflow (unterminated token)");
    115 		}
    116 	}
    117 	// unlike fltpgettoken, we create new node even if the line is empty
    118 	fltp->np = createfltnode(fltp->np, fltp->np, fltp->tbuf, fltp->ti);
    119 }