*Important:* Do `make clean` to work around a problem and prevent infinite rebuilds, https://github.com/davidgiven/ack/issues/68 I edit tokens.g in util/LLgen/src, so I regenerate tokens.c. The regeneration script bootstrap.sh can't find LLgen, but I can run the same command by typing the path to llgen.
		
			
				
	
	
		
			139 lines
		
	
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			139 lines
		
	
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* $Id$ */
 | 
						|
/*
 | 
						|
 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | 
						|
 * See the copyright notice in the ACK home directory, in the file "Copyright".
 | 
						|
 */
 | 
						|
/* p a t t e r n . c
 | 
						|
 *
 | 
						|
 * Deals with the pattern stuff.
 | 
						|
 * it maintains a table of information about the patterns
 | 
						|
 * Functions : addpattern() and printpatterns()
 | 
						|
 */
 | 
						|
 | 
						|
#include <stdlib.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <string.h>
 | 
						|
#include <ctype.h>
 | 
						|
#include "misc.h"
 | 
						|
#include "symtab.h"
 | 
						|
 | 
						|
struct pattern {
 | 
						|
    char *p_constraint;			/* constraint of this pattern */
 | 
						|
    int p_lineno, 			/* line number of constraint */
 | 
						|
        p_npat, 			/* # of instructions in pattern */
 | 
						|
        p_nrepl;			/* # of instructions in replacement */
 | 
						|
};
 | 
						|
 | 
						|
static struct pattern *pattable,	/* ptr to pattern array */
 | 
						|
		      *current,		/* ptr to first unoccupied el of
 | 
						|
					 * pattern array
 | 
						|
					 */
 | 
						|
		      *maxpat;		/* if beyond this, new space must
 | 
						|
					 * be allocated
 | 
						|
					 */
 | 
						|
 | 
						|
addpattern(str,l,np,nr) char *str; {
 | 
						|
    /*
 | 
						|
     * Just add a pattern to the list.
 | 
						|
     * "str" is the constraint, "l" is the line number,
 | 
						|
     * "np" is the number of instructions in the pattern,
 | 
						|
     * "nr" is the number of instructions in the replacement
 | 
						|
     * Space is allocated in chunks of 50
 | 
						|
     */
 | 
						|
    register struct pattern *p;
 | 
						|
 | 
						|
    if (!pattable) {		/* No space allocated yet */
 | 
						|
	pattable = (struct pattern *) malloc(50 * sizeof *pattable);
 | 
						|
	current = pattable;
 | 
						|
	maxpat = pattable + 50;
 | 
						|
    }
 | 
						|
    if (current >= maxpat) {	/* Allocate some new space */
 | 
						|
	p = pattable;
 | 
						|
	pattable = (struct pattern *) realloc(
 | 
						|
		(char *) pattable,
 | 
						|
		(unsigned) (sizeof *pattable * (50 + (maxpat - pattable))));
 | 
						|
	current = pattable + (current - p);
 | 
						|
	maxpat = pattable + (maxpat - p) + 50;
 | 
						|
    }
 | 
						|
    p = current++;
 | 
						|
    p->p_constraint = str;
 | 
						|
    p->p_lineno = l;
 | 
						|
    p->p_npat = np;
 | 
						|
    p->p_nrepl = nr;
 | 
						|
}
 | 
						|
 | 
						|
static
 | 
						|
prconstraint(str) char *str; {
 | 
						|
    /*
 | 
						|
     * prints a constraint, with variable names replaced
 | 
						|
     */
 | 
						|
    char c;
 | 
						|
    register char *p, *q;
 | 
						|
    struct symtab *name;
 | 
						|
 | 
						|
    p = str;
 | 
						|
    while (*p) {
 | 
						|
	if (isupper(*p) || islower(*p) || *p == '_') {
 | 
						|
	    /*
 | 
						|
	     * Start of identifier
 | 
						|
	     */
 | 
						|
	    q = p + 1;
 | 
						|
	    while (*q && (
 | 
						|
		   isupper(*q) || islower(*q) || isdigit(*q) || *q == '_')) {
 | 
						|
		q++;
 | 
						|
	    }
 | 
						|
	    c = *q;
 | 
						|
	    *q = '\0';
 | 
						|
	    /* Temporarily let it end with null byte */
 | 
						|
	    name = findident(p,LOOKING,&idtable);
 | 
						|
	    if (name) {		/* yeah, it was a variable */
 | 
						|
		fprintf(genc,"var[%d].value", name->s_num);
 | 
						|
	    }
 | 
						|
	    else if (!strcmp(p, "ANY")) {
 | 
						|
		fputs("ANY.value", genc);
 | 
						|
	    }
 | 
						|
	    else fputs(p,genc);
 | 
						|
	    /* Now replace null byte with whatever used to be there */
 | 
						|
	    *q = c;
 | 
						|
	    p = q;
 | 
						|
	}
 | 
						|
	else {
 | 
						|
	    putc(*p,genc);
 | 
						|
	    p++;
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
printpatterns() {
 | 
						|
    /*
 | 
						|
     * Prints the pattern_descr table and generates the routine
 | 
						|
     * "check_constraint"
 | 
						|
     */
 | 
						|
    register struct pattern *p;
 | 
						|
    register i;
 | 
						|
 | 
						|
    p = pattable;
 | 
						|
    i = 1;
 | 
						|
    fputs("struct pattern_descr patterns[] = {\n", genc);
 | 
						|
    while (p != current) {
 | 
						|
	fprintf(genc," {%d,pat%d,%d,rep%d,},\n",
 | 
						|
			p->p_npat, i, p->p_nrepl, i);
 | 
						|
	p++;
 | 
						|
	i++;
 | 
						|
    }
 | 
						|
    fputs("};\n", genc);
 | 
						|
    fputs("int\ncheck_constraint(patno){\n\tint r;\n\tswitch(patno){\n",genc);
 | 
						|
    p = pattable;
 | 
						|
    while (p < current) {
 | 
						|
	if (p->p_constraint) {
 | 
						|
	    /* The pattern has a constraint */	
 | 
						|
	    fprintf(genc,"\tcase %d :\n",p - pattable);
 | 
						|
	    fprintf(genc,linedir,p->p_lineno,inpfile);	/* linedirective */
 | 
						|
	    fputs("\tr = (",genc);
 | 
						|
	    prconstraint(p->p_constraint);
 | 
						|
	    fputs("); break;\n",genc);
 | 
						|
	}
 | 
						|
	p++;
 | 
						|
    }
 | 
						|
    fputs("\tdefault :\n\t\tr = 1;\n\t}\n\treturn r;\n}\n\n",genc);
 | 
						|
}
 |