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

⟦8a0485f77⟧ TextFile

    Length: 6422 (0x1916)
    Types: TextFile
    Notes: UNIX file
    Names: »awk2.c«

Derivation

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

TextFile

/*
 * AWK - part 2
 * Initialisation, and
 * other compiler support.
 * Symbol table maintenance
 * and lookup.
 */

#include "awk.h"
#include "y.tab.h"

void	keyenter();
void	funcenter();

typedef	struct	FUNC {
	int	(*f_funcp)();
	char	*f_name;
	char	f_minarg;		/* Minimum number of arguments */
	char	f_maxarg;		/* Maximum # args (-1 = variable) */
}	FUNC;

FUNC	functions[] = {
	f_length, "length", 0, 1,
	f_sqrt, "sqrt", 1, 1,
	f_log, "log", 1, 1,
	f_exp, "exp", 1, 1,
	f_int, "int", 1, 1,
	f_substr, "substr", 2, 3,
	f_index, "index", 2, 2,
	f_sprintf, "sprintf", 1, -1,
	f_split, "split", 2, 3,
	f_abs, "abs", 1, 1,
};

typedef	struct	KEYW	{
	int	k_lval;
	char	*k_name;
}	KEYW;

KEYW	keywords[] = {
	BEGIN_, "BEGIN",
	END_, "END",
	PRINT_, "print",
	PRINTF_, "printf",
	IF_, "if",
	ELSE_, "else",
	WHILE_, "while",
	FOR_, "for",
	IN_, "in",
	BREAK_, "break",
	CONTINUE_, "continue",
	NEXT_, "next",
	EXIT_, "exit",
};

/*
 * Initialisation --
 * Turn on buffering for output.
 * Initialse static constant values,
 * install keywords,
 * and install built-in functions.
 */
awkinit()
{
	setbuf(stdin, inbuf);
	setbuf(stdout, outbuf);
	setbuf(stderr, NULL);
	/*
	 * Initialise keywords into
	 * the symbol table.
	 */
	{
		register KEYW *kp;

		for (kp = keywords; kp < endof(keywords); kp++)
			keyenter(kp->k_name, kp->k_lval);
	}
	/*
	 * Install functions into symbol
	 * table.
	 */
	{
		register FUNC *fp;

		for (fp = functions; fp < endof(functions); fp++)
			funcenter(fp->f_name, fp->f_funcp, fp->f_minarg,
			    fp->f_maxarg);
	}
	xzero.t_INT = 0;
	xone.t_INT = 1;
	xone.t_op = xzero.t_op = ATERM;
	xone.t_flag = xzero.t_flag = T_INT|T_NUM;
	xfield0.n_op = AFIELD;
	xfield0.n_O1 = &xzero;
	/*
	 * Set up the built-in variables.
	 */
	NRp = install("NR", (INT)0);
	NFp = install("NF", (INT)0);
	FILENAMEp = lookup("FILENAME");
	sassign(FSp = install("FS", (INT)0), " \t\n");
	sassign(RSp = install("RS", (INT)0), "\n");
	sassign(OFSp = install("OFS", (INT)0), " ");
	sassign(ORSp = install("ORS", (INT)0), "\n");
	sassign(OFMTp = install("OFMT", (INT)0), "%D");
}

/*
 * Lookup an identifier - `id' and
 * if it is not found, initialise it
 * with the NULL string.
 * The hash value is the sum of all
 * the characters in the name +
 * the length of the name.
 */
NODE *
lookup(id)
char *id;
{
	register char *ip;
	register TERM *tp;
	register unsigned hash;
	register unsigned nb;

	hash = 0;
	nb = sizeof (char);
	for (ip = id; *ip != '\0'; hash++, nb++)
		hash += *ip++;
	for (tp = symtab[hash%NHASH]; tp != NULL; tp = tp->t_next)
		if (hash==tp->t_hval && tp->t_flag&T_VAR
		    && streq(tp->t_name, id))
			return (tp);
	tp = (TERM *)xalloc(sizeof(NODE) + nb);
	strcpy(tp->t_name, id);
	tp->t_STRING = xalloc(sizeof(char));
	tp->t_STRING[0] = '\0';
	tp->t_op = ATERM;
	tp->t_flag = T_VAR|T_ALLOC;
	tp->t_hval = hash;
	tp->t_ahval = -1;
	tp->t_next = symtab[hash %= NHASH];
	symtab[hash] = tp;
	return ((NODE *)tp);
}

/*
 * Lookup for an array.
 * Arguments are `array' and `index'
 * (both strings).  Hashing  is an
 * extension of that in lookup().
 * New array elements are given value the
 * NULL string.
 */
NODE *
alookup(array, index)
char *array;
char *index;
{
	register char *ip;
	register TERM *tp;
	register unsigned hash;
	register unsigned nba, nbi;
	register unsigned hash2;

	hash = 0;
	nba = nbi = sizeof (char);
	for (ip = array; *ip != '\0'; hash++, nba++)
		hash += *ip++;
	hash2 = hash;
	for (ip = index; *ip != '\0'; hash++, nbi++)
		hash += *ip++;
	for (tp = symtab[hash % NHASH]; tp != NULL; tp = tp->t_next)
		if (hash==tp->t_hval && tp->t_flag&T_ARRAY
		  && streq(tp->t_name, array) && streq(tp->t_name+nba, index))
			return (tp);
	tp = (TERM *)xalloc(sizeof(NODE) + nba + nbi);
	strcpy(tp->t_name, array);
	strcpy(tp->t_name+nba, index);
	tp->t_STRING = xalloc(sizeof(char));
	tp->t_STRING[0] = '\0';
	tp->t_op = ATERM;
	tp->t_flag = T_ARRAY|T_ALLOC;
	tp->t_hval = hash;
	tp->t_ahval = hash2;
	tp->t_next = symtab[hash %= NHASH];
	symtab[hash] = tp;
	return ((NODE *)tp);
}

/*
 * Install a built-in integer
 * name with value `val'.
 */
NODE *
install(id, val)
char *id;
INT val;
{
	register NODE *np;

	np = lookup(id);
	np->t_flag |= T_NUM|T_INT;
	free(np->t_STRING);
	np->t_INT = val;
	return (np);
}

/*
 * Enter a keyword in the symbol table.
 * `lval' is the lexical value of the keyword
 * and the TERM type is `AKEYW'.
 */
void
keyenter(word, lval)
char *word;
int lval;
{
	register char *ip;
	register unsigned hash;
	register TERM *tp;
	register int nb;

	hash = 0;
	nb = sizeof (char);
	for (ip = word; *ip != '\0'; hash++, nb++)
		hash += *ip++;
	tp = (TERM *)xalloc(nb + sizeof(TERM));
	tp->t_hval = hash;
	tp->t_op = AKEYW;
	tp->t_flag = T_ALLOC|T_VAR;
	strcpy(tp->t_name, word);
	tp->t_INT = lval;
	tp->t_next = symtab[hash %= NHASH];
	symtab[hash] = tp;
}

/*
 * Enter a function name into the
 * symbol table.
 * `min' and `max' are the minimum and
 * maximum number of arguments, respectively.
 */
void
funcenter(name, fun, min, max)
char *name;
int (*fun)();
int min, max;
{
	register char *np;
	register unsigned hash;
	register TERM *tp;
	register unsigned nb;

	hash = 0;
	nb = sizeof (char);
	for (np = name; *np != '\0'; hash++, nb++)
		hash += *np++;
	tp = (TERM *)xalloc(nb + sizeof(TERM));
	tp->t_hval = hash;
	tp->t_op = AFUNC;
	tp->t_flag = T_ALLOC|T_VAR;
	strcpy(tp->t_name, name);
	tp->t_FUNC = fun;
	tp->t_MINARG = min;
	tp->t_MAXARG = max;
	tp->t_next = symtab[hash %= NHASH];
	symtab[hash] = tp;
}

/*
 * Assign a new value to a string.
 * It produces a static string.
 */
sassign(np, s)
register NODE *np;
STRING s;
{
	if ((np->t_flag & (T_ALLOC|T_NUM)) == T_ALLOC)
		free(np->t_STRING);
	np->t_flag &= ~(T_ALLOC|T_NUM);
	np->t_STRING = s;
}

/*
 * Assign an INT to a node.
 */
iassign(np, i)
register NODE *np;
INT i;
{
	if ((np->t_flag & (T_ALLOC|T_NUM)) == T_ALLOC)
		free(np->t_STRING);
	np->t_flag &= ~T_ALLOC;
	np->t_flag |= T_INT|T_NUM;
	np->t_INT = i;
}

/*
 * Initialise (or reset) the mapping
 * table for field extraction.  It is
 * set to non-zero for every character
 * that can end a field + '\0'
 * Note that FSMAP is defined over `wordbuf'
 * which is only used lexically and by `sprintf'
 * Therefore this routine must be called if this
 * buffer is disturbed.
 */
fsmapinit(fsp)
register char *fsp;
{
	register char *cp;

	for (cp = FSMAP; cp < &FSMAP[NCSET]; )
		*cp++ = 0;
	while (*fsp != '\0')
		FSMAP[*fsp++] = 1;
}