DataMuseum.dk

Presents historical artifacts from the history of:

Commodore CBM-900

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Commodore CBM-900

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦ac78d2f36⟧ TextFile

    Length: 6570 (0x19aa)
    Types: TextFile
    Notes: UNIX file
    Names: »test.y«

Derivation

└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
    └─⟦f4b8d8c84⟧ UNIX V7 Filesystem
        └─ ⟦this⟧ »cmd/test/test.y« 

TextFile

%{
/*
 * Set return status based on
 * various specified conditions,
 * mostly related to files.
 * Used mostly in shell files.
 */

#include <stdio.h>
#include <stat.h>
#include <access.h>
#include "testnode.h"

#define	NPRIM	(sizeof(prims)/sizeof(prims[0]))
#define	NFNAME	500		/* size of filename buffer */
%}
%start	command

%union	{
	NODE *nodeptr;
	char *fname;
	}

%left	OR
%left	AND
%left	'!'
%token	_R _W _F _D _S _T _Z _N
%token	SEQ SNEQ
%token	_EQ _NE _GT _GE _LT _LE
%token	<fname> STR
%type	<nodeptr> exp

%%

command:
	exp '\n'		{ code = $1; return; }
	;

exp:
        '(' exp ')'		{ $$ = $2; }
      | '!' exp			{ $$ = bnode('!', $2, NULL); }
      | exp OR exp		{ $$ = bnode(OR, $1, $3); }
      | exp AND exp		{ $$ = bnode(AND, $1, $3); }
      | _R STR			{ $$ = lnode(xr, $2, NULL); }
      | _W STR			{ $$ = lnode(xw, $2, NULL); }
      | _F STR			{ $$ = lnode(xf, $2, NULL); }
      | _D STR			{ $$ = lnode(xd, $2, NULL); }
      | _S STR			{ $$ = lnode(xs, $2, NULL); }
      | _T STR			{ $$ = lnode(xt, $2, NULL); }
      | _T			{ $$ = lnode(xt, "1", NULL); }
      | _Z STR			{ $$ = lnode(xz, $2, NULL); }
      | _N STR			{ $$ = lnode(xn, $2, NULL); }
      | STR SEQ STR		{ $$ = lnode(xseq, $1, $3); }
      | STR SNEQ STR		{ $$ = lnode(xsneq, $1, $3); }
      | STR _EQ STR		{ $$ = lnode(xeq, $1, $3); }
      | STR _NE STR		{ $$ = lnode(xne, $1, $3); }
      | STR _GT STR		{ $$ = lnode(xgt, $1, $3); }
      | STR _GE STR		{ $$ = lnode(xge, $1, $3); }
      | STR _LT STR		{ $$ = lnode(xlt, $1, $3); }
      | STR _LE STR		{ $$ = lnode(xle, $1, $3); }
      | STR			{ $$ = lnode(xn, $1, NULL); }
	;

%%
struct	prim	{
	char	*p_name;
	int	p_lval;
}	prims[] = {
	"-r", _R,
	"-w", _W,
	"-f", _F,
	"-d", _D,
	"-s", _S,
	"-t", _T,
	"-z", _Z,
	"-n", _N,
	"-eq", _EQ,
	"-ne", _NE,
	"-gt", _GT,
	"-ge", _GE,
	"-lt", _LT,
	"-le", _LE,
	"-o", OR,
	"-a", AND,
};


char	**gav;
int	gac;

struct	stat	sb;

NODE	*code;

char	*next();
NODE	*bnode();
NODE	*lnode();
long	atol();
int	xr();
int	xw();
int	xf();
int	xd();
int	xs();
int	xt();
int	xz();
int	xn();
int	xseq();
int	xsneq();
int	xeq();
int	xne();
int	xgt();
int	xge();
int	xlt();

main(argc, argv)
char *argv[];
{
	gav = argv+1;
	gac = argc-1;
	if (argv[0][0]=='[' && argv[0][1]=='\0') {
		if (strcmp(argv[gac], "]") != 0)
			tsterr("unbalanced [..]");
		gac--;
	}
	if (gac == 0)
		exit(1);
	yyparse();
	exit(!execute(code));
}

/*
 * Lexical analyser
 */
yylex()
{
	register char *ap;
	register struct prim *pp;

	if ((ap = next()) == NULL)
		return ('\n');
	if (ap[1] == '\0')
		if (ap[0]=='(' || ap[0]==')' || ap[0]=='!')
			return (ap[0]);
	if (ap[0]=='!' && ap[1]=='=' && ap[2]=='\0')
		return (SNEQ);
	if (ap[0]=='=' && ap[1]=='\0')
		return (SEQ);
	if (*ap == '-')
		for (pp = prims; pp < &prims[NPRIM]; pp++)
			if (strcmp(pp->p_name, ap) == 0)
				return (pp->p_lval);
	yylval.fname = ap;
	return (STR);
}

yyerror()
{
	fprintf(stderr, "Test expression syntax error\n");
	usage();
}

/*
 * Return the next argument from the arg list.
 */
char *
next()
{
	if (gac < 1)
		return (NULL);
	gac--;
	return (*gav++);
}

/*
 * Build an expression tree node (non-leaf)
 */
NODE *
bnode(op, left, right)
int op;
NODE *left, *right;
{
	register NODE *np;
	char *malloc();

	if ((np = (NODE *)malloc(sizeof (NODE))) == NULL)
		tsterr("Out of space");
	np->n_un.n_op = op;
	np->n_left = left;
	np->n_right = right;
	return (np);
}

/*
 * Build a leaf node in expression tree.
 */
NODE *
lnode(fn, str1, str2)
int (*fn)();
char *str1, *str2;
{
	register NODE *np;
	char *malloc();

	if ((np = (NODE *)malloc(sizeof (NODE))) == NULL)
		tsterr("Out of space");
	np->n_left = np->n_right = NULL;
	np->n_un.n_fun = fn;
	np->n_s1 = str1;
	np->n_s2 = str2;
	return (np);
}

/*
 * Execute compiled code.
 */
execute(np)
register NODE *np;
{
	if (np->n_left != NULL)
		switch (np->n_un.n_op) {
		case AND:
			if (execute(np->n_left) && execute(np->n_right))
				return (1);
			return (0);

		case OR:
			if (execute(np->n_left) || execute(np->n_right))
				return (1);
			return (0);

		case '!':
			return (!execute(np->n_left));

		default:
			tsterr("Panic: bad tree (op %d)", np->n_un.n_op);
		}
	else
		return ((*np->n_un.n_fun)(np));
	/* NOTREACHED */
}

/*
 * Check to see if the file exists
 * and if readable.
 */
xr(np)
NODE *np;
{
	return (access(np->n_s1, AREAD) >= 0);
}

/*
 * Check if the file exists and is
 * writeable.
 */
xw(np)
NODE *np;
{
	return (access(np->n_s1, AWRITE) >= 0);
}

/*
 * Check if the file exists and is not
 * a directory.
 */
xf(np)
NODE *np;
{
	return (stat(np->n_s1, &sb)>=0 && (sb.st_mode&S_IFMT)!=S_IFDIR);
}

/*
 * Check to see if the file exists
 * and is a directory.
 */
xd(np)
NODE *np;
{
	return (stat(np->n_s1, &sb)>=0 && (sb.st_mode&S_IFMT)==S_IFDIR);
}

/*
 * Check to see if the file exists
 * and has a non-zero size.
 */
xs(np)
NODE *np;
{
	return (stat(np->n_s1, &sb)>=0 && sb.st_size>0);
}

/*
 * Check to see if the file
 * descriptor is associated
 * with a terminal.
 */
xt(np)
NODE *np;
{
	return (isatty(atoi(np->n_s1)));
}

/*
 * True if the length of the given
 * string is zero.
 */
xz(np)
NODE *np;
{
	return (np->n_s1[0] == '\0');
}

/*
 * True if the length of the given
 * string is non-zero.
 */
xn(np)
NODE *np;
{
	return (np->n_s1[0] != '\0');
}

/*
 * True if the two strings are
 * lexicographically equal.
 */
xseq(np)
register NODE *np;
{
	return (strcmp(np->n_s1, np->n_s2) == 0);
}

/*
 * True if the two strings are
 * lexicographically unequal.
 */
xsneq(np)
register NODE *np;
{
	return (strcmp(np->n_s1, np->n_s2) != 0);
}

/*
 * True if the two numbers are
 * equal.
 */
xeq(np)
register NODE *np;
{
	return (atol(np->n_s1) == atol(np->n_s2));
}

/*
 * True if the two numbers are
 * not equal.
 */
xne(np)
register NODE *np;
{
	return (atol(np->n_s1) != atol(np->n_s2));
}

/*
 * True if the first number is
 * greater than the second.
 */
xgt(np)
register NODE *np;
{
	return (atol(np->n_s1) > atol(np->n_s2));
}

/*
 * True if the first number is
 * greater than or equal to the second.
 */
xge(np)
register NODE *np;
{
	return (atol(np->n_s1) >= atol(np->n_s2));
}

/*
 * True if the first number is
 * less than the second.
 */
xlt(np)
register NODE *np;
{
	return (atol(np->n_s1) < atol(np->n_s2));
}

/*
 * True if the first number is
 * less than or equal to the second.
 */
xle(np)
register NODE *np;
{
	return (atol(np->n_s1) <= atol(np->n_s2));
}

/*
 * Error messages.
 */
/* VARARGS */
tsterr(x)
{
	fprintf(stderr, "test: %r\n", &x);
	exit(1);
}

usage()
{
	fprintf(stderr, "Usage: test expression\n");
	exit(1);
}