⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 acd.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		if (n != 1) { key_usage(""); return; }		if (phase != INIT) { inappropriate(); return; }		if (talk()) prin2n(p);		argscan();		if (p->car->name[0] == 'c') compile();		nextpc= next;	} else {		/* A UNIX command. */		t= evaluate(inc(pc->line), IMPLODE);		unix_exec(t);		dec(t);	}}void execute(exec_t how, unsigned indent)/* Execute (or skip) all lines with at least the given indent. */{	int work= 0;	/* Need to execute at least one line. */	unsigned firstline;	unsigned nice_indent= 0;	/* 0 = Don't know what's nice yet. */	if (pc == nil) return;	/* End of program. */	firstline= pc->lineno;	if (how == DONT) {		/* Skipping a body, but is there another guard? */		pc= pc->next;		if (pc != nil && pc->indent < indent && pc->line != nil) {			/* There is one!  Bail out, then it get's executed. */			return;		}	} else {		/* Skip lines with a lesser indentation, they are guards for		 * the same substatements.  Don't go past empty lines.		 */		while (pc != nil && pc->indent < indent && pc->line != nil)			pc= pc->next;	}	/* Execute all lines with an indentation of at least "indent". */	while (pc != nil && pc->indent >= indent) {		if (pc->indent != nice_indent && how == DOIT) {			if (nice_indent != 0) {				fprintf(stderr,			"\"%s\", line %u: (warning) sudden indentation shift\n",					descr, pc->lineno);			}			nice_indent= pc->indent;		}		nextpc= pc->next;		if (how == DOIT) exec_one();		pc= nextpc;		work= 1;	}	if (indent > 0 && !work) {		fprintf(stderr, "\"%s\", line %u: empty body, no statements\n",			descr, firstline);		action= 0;	}}int argmatch(int shift, cell_t *match, cell_t *match1, char *arg1)/* Try to match an arg rule to the input file list L_args.  Execute the arg * body (pc is set to it) on success. */{	cell_t *oldval, *v;	int m, oldflags;	size_t i, len;	int minus= 0;	if (shift) {		/* An argument has been accepted and may be shifted to $*. */		cell_t **oldpstar= pV_star;		*pV_star= L_args;		L_args= *(pV_star= &L_args->cdr);		*pV_star= nil;		if (argmatch(0, match->cdr, nil, nil)) return 1;		/* Undo the damage. */		*pV_star= L_args;		L_args= *(pV_star= oldpstar);		*pV_star= nil;		return 0;	}	if (match == nil) {		/* A full match, execute the arg body. */		/* Enable $>. */		V_out->flags= W_SET|W_LOCAL;		if (verbose >= 3) {			prin2(pc->line);			printf(" =\b=\b= ");			prin2n(V_star->value);		}		execute(DOIT, pc->indent+1);		/* Append $> to the file list. */		if (V_out->value != nil) {			*pL_files= cons(CELL, V_out->value);			pL_files= &(*pL_files)->cdr;		}		/* Disable $>. */		V_out->value= nil;		V_out->flags= W_SET|W_LOCAL|W_RDONLY;		return 1;	}	if (L_args == nil) return 0;	/* Out of arguments to match. */	/* Match is a list of words, substs and strings containing letters and	 * substs.  Match1 is the current element of the first element of match.	 * Arg1 is the current character of the first element of L_args.	 */	if (match1 == nil) {		/* match1 is at the end of a string, then arg1 must also. */		if (arg1 != nil) {			if (*arg1 != 0) return 0;			return argmatch(1, match, nil, nil);		}		/* If both are nil: Initialize. */		match1= match->car;		arg1= L_args->car->name;		/* A subst may not match a leading '-'. */		if (arg1[0] == '-') minus= 1;	}	if (match1->type == WORD && strcmp(match1->name, arg1) == 0) {		/* A simple match of an argument. */		return argmatch(1, match, nil, nil);	}	if (match1->type == SUBST && !minus) {		/* A simple match of a subst. */		/* The variable gets the first of the arguments as its value. */		v= match1->subst;		if (v->flags & W_RDONLY) return 0;	/* ouch */		oldflags= v->flags;		v->flags= W_SET|W_LOCAL|W_RDONLY;		oldval= v->value;		v->value= inc(L_args->car);		m= argmatch(1, match, nil, nil);		/* Recover the value of the variable. */		dec(v->value);		v->flags= oldflags;		v->value= oldval;		return m;	}	if (match1->type != STRING) return 0;	/* Match the first item in the string. */	if (match1->car == nil) return 0;	if (match1->car->type == LETTER			&& match1->car->letter == (unsigned char) *arg1) {		/* A letter matches, try the rest of the string. */		return argmatch(0, match, match1->cdr, arg1+1);	}	/* It can only be a subst in a string now. */	len= strlen(arg1);	if (match1->car->type != SUBST || minus || len == 0) return 0;	/* The variable can match from 1 character to all of the argument.	 * Matching as few characters as possible happens to be the Right Thing.	 */	v= match1->car->subst;	if (v->flags & W_RDONLY) return 0;	/* ouch */	oldflags= v->flags;	v->flags= W_SET|W_LOCAL|W_RDONLY;	oldval= v->value;	m= 0;	for (i= match1->cdr == nil ? len : 1; !m && i <= len; i++) {		v->value= findnword(arg1, i);		m= argmatch(0, match, match1->cdr, arg1+i);		dec(v->value);	}	/* Recover the value of the variable. */	v->flags= oldflags;	v->value= oldval;	return m;}void argscan(void)/* Match all the arguments to the arg rules, those that don't match are * used as files for transformation. */{	rule_t *rule;	int m;	phase= SCAN;	/* Process all the arguments. */	while (L_args != nil) {		pV_star= &V_star->value;		/* Try all the arg rules. */		m= 0;		for (rule= rules; !m && rule != nil; rule= rule->next) {			if (rule->type != ARG) continue;			pc= rule->prog;			m= argmatch(0, rule->match, nil, nil);		}		dec(V_star->value);		V_star->value= nil;		/* On failure, add the first argument to the list of files. */		if (!m) {			*pL_files= L_args;			L_args= *(pL_files= &L_args->cdr);			*pL_files= nil;		}	}	phase= INIT;}int member(cell_t *p, cell_t *l)/* True if p is a member of list l. */{	while (l != nil && l->type == CELL) {		if (p == l->car) return 1;		l= l->cdr;	}	return p == l;}long basefind(cell_t *f, cell_t *l)/* See if f has a suffix in list l + set the base name of f. * -1 if not found, preference number for a short basename otherwise. */{	cell_t *suff;	size_t blen, slen;	char *base;	/* Determine base name of f, with suffix. */	if ((base= strrchr(f->name, '/')) == nil) base= f->name; else base++;	blen= strlen(base);	/* Try suffixes. */	while (l != nil) {		if (l->type == CELL) {			suff= l->car; l= l->cdr;		} else {			suff= l; l= nil;		}		if (f->flags & W_SUFF) {			/* F has a suffix imposed on it. */			if (f->suffix == suff) return 0;			continue;		}		slen= strlen(suff->name);		if (slen < blen && strcmp(base+blen-slen, suff->name) == 0) {			/* Got it! */			dec(f->base);			f->base= findnword(base, blen-slen);			return 10000L * (blen - slen);		}	}	return -1;}#define NO_PATH		2000000000	/* No path found yet. */long shortest;		/* Length of the shortest path as yet. */rule_t *findpath(long depth, int seek, cell_t *file, rule_t *start)/* Find the path of the shortest transformation to the stop suffix. */{	rule_t *rule;	if (action == 0) return nil;	if (start == nil) {		/* No starting point defined, find one using "file". */		for (rule= rules; rule != nil; rule= rule->next) {			if (rule->type < TRANSFORM) continue;			if ((depth= basefind(file, rule->from)) >= 0) {				if (findpath(depth, seek, nil, rule) != nil)					return rule;			}		}		return nil;	}	/* Cycle? */	if (start->path != nil) {		/* We can't have cycles through combines. */		if (start->type == COMBINE) {			fprintf(stderr,				"\"%s\": contains a combine-combine cycle\n",				descr);			action= 0;		}		return nil;	}	/* Preferred transformations are cheap. */	if (start->flags & R_PREFER) depth-= 100;	/* Try to go from start closer to the stop suffix. */	for (rule= rules; rule != nil; rule= rule->next) {		if (rule->type < TRANSFORM) continue;		if (member(start->to, rule->from)) {			start->path= rule;			rule->npaths++;			if (findpath(depth+1, seek, nil, rule) != nil)				return start;			start->path= nil;			rule->npaths--;		}	}	if (V_stop == nil) {		fprintf(stderr, "\"%s\": no stop suffix has been defined\n",			descr);		action= 0;		return nil;	}	/* End of the line? */	if (start->to == V_stop) {		/* Got it. */		if (seek) {			/* Second hunt, do we find the shortest? */			if (depth == shortest) return start;		} else {			/* Is this path shorter than the last one? */			if (depth < shortest) shortest= depth;		}	}	return nil;	/* Fail. */}void transform(rule_t *rule)/* Transform the file(s) connected to the rule according to the rule. */{	cell_t *file, *in, *out;	char *base;	/* Let $* be the list of input files. */	while (rule->wait != nil) {		file= rule->wait;		rule->wait= file->cdr;		file->cdr= V_star->value;		V_star->value= file;	}	/* Set $< to the basename of the first input file. */	file= file->car;	V_in->value= in= inc(file->flags & W_SUFF ? file : file->base);	file->flags&= ~W_SUFF;	/* Set $> to the output file name of the transformation. */	out= newcell();	out->type= WORD;	base= rule->path == nil ? in->name : maketemp();	out->name= allocate(nil,		(strlen(base)+strlen(rule->to->name)+1) * sizeof(*out->name));	strcpy(out->name, base);	if (rule->path == nil || strchr(rule->to->name, '/') == nil)		strcat(out->name, rule->to->name);	out= inc(out);	if (rule->path != nil) out->flags|= W_TEMP;	V_out->value= out;	V_out->flags= W_SET|W_LOCAL;	/* Do a transformation.  (Finally) */	if (verbose >= 3) {		printf("%s ", rule->type==TRANSFORM ? "transform" : "combine");		prin2(V_star->value);		printf(" %s\n", out->name);	}	pc= rule->prog;	execute(DOIT, pc->indent+1);	/* Hand $> over to the next rule, it must be a single word. */	out= evaluate(V_out->value, IMPLODE);	if (wordlist(&out, 1) != 1) {		fprintf(stderr,		"\"%s\", line %u: $> should be returned as a single word\n",			descr, rule->prog->lineno);		action= 0;	}	if ((rule= rule->path) != nil) {		/* There is a next rule. */		dec(out->base);		out->base= in;		/* Basename of input file. */		file= inc(newcell());		file->car= out;		file->cdr= rule->wait;		rule->wait= file;	} else {		dec(in);		dec(out);	}	/* Undo the damage to $*, $<, and $>. */	dec(V_star->value);	V_star->value= nil;	V_in->value= nil;	V_out->value= nil;	V_out->flags= W_SET|W_LOCAL|W_RDONLY;}void compile(void){	rule_t *rule;	cell_t *file, *t;	phase= COMPILE;	/* Implode the files list. */	L_files= evaluate(L_files, IMPLODE);	if (wordlist(&L_files, 0) < 0) {		fprintf(stderr, "\"%s\": An assignment to $> contained junk\n",			descr);		action= 0;	}	while (action != 0 && L_files != nil) {		file= L_files->car;		/* Initialize. */		shortest= NO_PATH;		for (rule= rules; rule != nil; rule= rule->next)			rule->path= nil;		/* Try all possible transformation paths. */		(void) findpath(0L, 0, file, nil);		if (shortest == NO_PATH) {	/* Can't match the file. */			fprintf(stderr,			"%s: %s: can't compile, no transformation applies\n",				program, file->name);			action= 0;			return;		}		/* Find the first short path. */		if ((rule= findpath(0L, 1, file, nil)) == nil) return;		/* Transform the file until you hit a combine. */		t= inc(newcell());		t->car= inc(file);		L_files= go(L_files, L_files->cdr);		t->cdr= rule->wait;		rule->wait= t;		while (action != 0 && rule != nil && rule->type != COMBINE) {			transform(rule);			rule= rule->path;		}	}	/* All input files have been transformed to combine rule(s).  Now	 * we need to find the combine rule with the least number of paths	 * running through it (this combine may be followed by another) and	 * transform from there.	 */	while (action != 0) {		int least;		rule_t *comb= nil;		for (rule= rules; rule != nil; rule= rule->next) {			rule->path= nil;			if (rule->type != COMBINE || rule->wait == nil)				continue;			if (comb == nil || rule->npaths < least) {				least= rule->npaths;				comb= rule;			}		}		/* No combine?  Then we're done. */		if (comb == nil) break;		/* Initialize. */		shortest= NO_PATH;		/* Try all possible transformation paths. */		(void) findpath(0L, 0, nil, comb);		if (shortest == NO_PATH) break;		/* Find the first short path. */		if ((rule= findpath(0L, 1, nil, comb)) == nil) return;		/* Transform until you hit another combine. */		do {			transform(rule);			rule= rule->path;		} while (action != 0 && rule != nil && rule->type != COMBINE);	}	phase= INIT;}cell_t *predef(char *var, char *val)/* A predefined variable var with value val, or a special variable. */{	cell_t *p, *t;	p= findword(var);	if (val != nil) {	/* Predefined. */		t= findword(val);		dec(p->value);		p->value= t;		p->flags|= W_SET;		if (verbose >= 3) {			prin1(p);			printf(" =\b=\b= ");			prin2n(t);		}	} else {		/* Special: $* and such. */		p->flags= W_SET|W_LOCAL|W_RDONLY;	}	t= inc(newcell());	t->car= p;	t->cdr= L_predef;	L_predef= t;	return p;}void usage(void){	fprintf(stderr,	"Usage: %s -v<n> -vn<n> -name <name> -descr <descr> -T <dir> ...\n",		program);	exit(-1);}int main(int argc, char **argv){	program_t *prog;	cell_t **pa;	int i;	/* Call name of the program, decides which description to use. */	if ((program= strrchr(argv[0], '/')) == nil)		program= argv[0];	else		program++;	/* Directory for temporary files. */	if ((template= getenv("TMPDIR")) == nil || *template == 0)		template= "/tmp";	/* Transform arguments to a list, processing the few ACD options. */	pa= &L_args;	for (i= 1; i < argc; i++) {		if (argv[i][0] == '-' && argv[i][1] == 'v') {			char *a= argv[i]+2;			if (*a == 'n') { a++; action= 1; }			verbose= 2;			if (*a != 0) {				verbose= strtoul(a, &a, 10);				if (*a != 0) usage();			}		} else		if (strcmp(argv[i], "-name") == 0) {			if (++i == argc) usage();			program= argv[i];		} else		if (strcmp(argv[i], "-descr") == 0) {			if (++i == argc) usage();			descr= argv[i];		} else		if (argv[i][0] == '-' && argv[i][1] == 'T') {			if (argv[i][2] == 0) {				if (++i == argc) usage();				template= argv[i];			} else				template= argv[i]+2;		} else {			/* Any other argument must be processed. */			*pa= cons(CELL, findword(argv[i]));			pa= &(*pa)->cdr;		}	}#ifndef DESCR	/* Default description file is based on the program name. */	if (descr == nil) descr= program;#else	/* Default description file is predefined. */	if (descr == nil) descr= DESCR;#endif	template= copystr(template);	/* Catch user signals. */	if (signal(SIGHUP, SIG_IGN) != SIG_IGN) signal(SIGHUP, interrupt);	if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, interrupt);	if (signal(SIGTERM, SIG_IGN) != SIG_IGN) signal(SIGTERM, interrupt);	/* Predefined or special variables. */	predef("PROGRAM", program);	predef("VERSION", version);#ifdef ARCH	predef("ARCH", ARCH);		/* Cross-compilers like this. */#endif	V_star= predef("*", nil);	V_in= predef("<", nil);	V_out= predef(">", nil);	/* Read the description file. */	if (verbose >= 3) printf("include %s\n", descr);	prog= get_prog();	phase= INIT;	pc= prog;	execute(DOIT, 0);	argscan();	compile();	/* Delete all allocated data to test inc/dec balance. */	while (prog != nil) {		program_t *junk= prog;		prog= junk->next;		dec(junk->file);		dec(junk->line);		deallocate(junk);	}	while (rules != nil) {		rule_t *junk= rules;		rules= junk->next;		dec(junk->from);		dec(junk->to);		dec(junk->wait);		deallocate(junk);	}	deallocate(template);	dec(V_stop);	dec(L_args);	dec(L_files);	dec(L_predef);	quit(action == 0 ? 1 : 0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -