Plan 9 from Bell Labs’s /usr/web/sources/contrib/pdt/sky/cmd/skywatch/cmd.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#include <u.h>
#include <libc.h>
#include <thread.h>
#include <bio.h>

#include "debug.h"
#include "lex.h"
#include "sky.h"

#include "dat.h"
#include "fns.h"

Lexer l;

struct Cmdnode *mkcmdnode(void);
Tok cmdeval(Cmdreg* reg, int depth);
int eqsig(Cmd *c1, Cmd *c2);
Tok (*(getfun)(struct Cmdnode*, Cmd*))(Tok*, int);

Cmdreg*
mkcmdreg(int fd)
{
	Cmdreg *reg;
	if((reg=malloc(sizeof(Cmdreg)))==nil)
		return nil;
	linit(&reg->l, fd, lexstart());
	if((reg->head=mkcmdnode())==nil){
		free(reg);
		return nil;
	}

	return reg;
}


int
cmdregister(Cmdreg *reg, Cmd *c)
{
	struct Cmdnode *head;
	head = reg->head;

	/* the tail node is always pre-allocated but unset */
	while(head->next){
		if(eqsig(c, head->c)){
			head->c->fun = c->fun;
			return 0;
		}
		head=head->next;
	}

	if((head->next=mkcmdnode())==nil)
		return Ememory;

	*(head->c) = *c;

	return 0;
}

void
cmdterm(Cmdreg *reg)
{
	struct Cmdnode *head, *nxt;
	head = reg->head;

	while(head){
		nxt = head->next;
		free(head->c);
		free(head);
		head = nxt;
	}

	lterm(&reg->l);
	free(reg);
}

Tok
cmdeval(Cmdreg* reg, int depth)
{
	struct Cmdnode *head;
	Tok t, argv[Cmaxargs];
	Cmd c;
	Tok (*efun)(Tok*, int);
	char *err;

	head = reg->head;
	memset(&c, 0, sizeof(Cmd));

	while(t = lnexttok(&reg->l), t.typ != Teof){
eval:		DBPRINT(20, "cmd.c:cmdeval tok: %d(%S)\n", t.typ, t.str);
		switch(t.typ){
		case Terror:
			err = "parse error";
error:		fprint(2, "%s in cmd %S L\"%S\"\n", err, *c.str ? c.str : L"nil", t.str);
			return t;
		case Tcmd:
			runestrncpy(c.str, t.str, Ltoksize+1);
			break;
		case Tpclose:
			if(depth <= 0){
				err = "unmatched pclose";
				goto error;
			}

			if((efun = getfun(head, &c)) == nil){
				err = "unrecognised function signature";
				goto error;
			}
			if((t = (*efun)(argv, c.argc)), t.typ == Terror){
				err = "invalid data";
				goto error;
			}
			DBIF(20) {
				fprint(2, "cmd %S with %d arg(s) in reverse:", c.str, c.argc);
				while(c.argc--) fprint(2, " %d(%S)", argv[c.argc].typ, argv[c.argc].str);
				fprint(2, ": success\n");
			}
			return t;
		case Tpopen:
			t = cmdeval(reg, depth+1);
			goto eval;
		case Tidentifier:
		case Tdecimal:
		case Tstr:
			c.argtyp[c.argc] = t.typ;
			argv[c.argc++] = t;
			break;
		}
	}
	return t;
}

void
cmdproc(void *reg)
{
	Tok t;
	while(t = cmdeval(reg, 0), t.typ != Teof){
		DBPRINT(20, "cmd.c:cmdproc eval: %d(%S)\n", t.typ, t.str);
	}
}

struct Cmdnode*
mkcmdnode(void)
{
	struct Cmdnode *h;
	if((h=malloc(sizeof(struct Cmdnode)))==nil)
		return nil;
	memset(h, 0, sizeof(struct Cmdnode));
	if((h->c=malloc(sizeof(Cmd)))==nil){
		free(h);
		return nil;
	}
	memset(h->c, 0, sizeof(Cmd));

	return h;
}

int
eqsig(Cmd *c1, Cmd *c2)
{
	int i, *a1, *a2;

	if(!c1 || !c2) return 0;
	/* negative argc matches any number */
	if(runestrncmp(c1->str, c2->str, Ltoksize+1) || c1->argc != c2->argc) return 0;
	for(i=0, a1=c1->argtyp, a2=c2->argtyp; i<c1->argc; i++)
		if(*a1++ != *a2++) return 0;

	return 1;	
}

Tok (*(getfun)(struct Cmdnode *h, Cmd *c))(Tok*, int)
{
	/* last node is always unset */
	while(h->next){
		if(eqsig(c, h->c)) return h->c->fun;
		h = h->next;
	}

	return nil;
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].