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

📄 acd.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
			execvp(argv[0], argv);			report(argv[0]);			exit(-1);		}	}	if (fd[0] >= 0) close(fd[0]);	if (fd[1] >= 0) close(fd[1]);	if (i >= 0 && action >= 2) {		/* Wait for the command to terminate. */		while ((r= wait(&status)) != pid && (r >= 0 || errno == EINTR));		if (status != 0) {			int sig= WTERMSIG(status);			if (!WIFEXITED(status)					&& sig != SIGINT && sig != SIGPIPE) {				fprintf(stderr, "%s: %s: Signal %d%s\n",					program, argv[0], sig,					status & 0x80 ? " - core dumped" : "");			}			action= 0;		}	}	deallocate(argv);}/* Special read-only variables ($*) and lists. */cell_t *V_star, **pV_star;cell_t *L_files, **pL_files= &L_files;cell_t *V_in, *V_out, *V_stop, *L_args, *L_predef;typedef enum exec { DOIT, DONT } exec_t;void execute(exec_t how, unsigned indent);int equal(cell_t *p, cell_t *q)/* Two lists are equal if they contain each others elements. */{	cell_t *t, *m1, *m2;	t= inc(newcell());	t->cdr= inc(newcell());	t->cdr->cdr= inc(newcell());	t->cdr->car= newcell();	t->cdr->car->type= MINUS;	t->cdr->car= inc(t->cdr->car);	/* Compute p - q. */	t->car= inc(p);	t->cdr->cdr->car= inc(q);	m1= evaluate(inc(t), IMPLODE);	dec(m1);	/* Compute q - p. */	t->car= q;	t->cdr->cdr->car= p;	m2= evaluate(t, IMPLODE);	dec(m2);	/* Both results must be empty. */	return m1 == nil && m2 == nil;}int wordlist(cell_t **pw, int atom)/* Check if p is a list of words, typically an imploded list.  Return * the number of words seen, -1 if they are not words (INPUT/OUTPUT?). * If atom is true than a list of one word is turned into a word. */{	int n= 0;	cell_t *p, **pp= pw;	while (*pp != nil) {		*pp= append(CELL, *pp);		p= (*pp)->car;		n= n >= 0 && p != nil && p->type == WORD ? n+1 : -1;		pp= &(*pp)->cdr;	}	if (atom && n == 1) *pw= go(*pw, (*pw)->car);	return n;}char *template;		/* Current name of a temporary file. */char *maketemp(void)/* Return a name that can be used as a temporary filename. */{	static char *tp= nil;	int i= 0;	if (tp == nil) {		size_t len= strlen(template);		template= allocate(template, (len+20) * sizeof(*template));		sprintf(template+len, "/acd%d", getpid());		tp= template + strlen(template);	}	for (;;) {		switch (tp[i]) {		case 0:		tp[i]= 'a';				tp[i+1]= 0;	return template;		case 'z':	tp[i++]= 'a';	break;		default:	tp[i]++;	return template;		}	}}cell_t *splitenv(char *env)/* Split a string from the environment into several words at whitespace * and colons.  Two colons (::) become a dot. */{	cell_t *r= nil, **pr= &r;	char *p;	do {		while (*env != 0 && isspace(*env)) env++;		if (*env == 0) break;		p= env;		while (*p != 0 && !isspace(*p) && *p != ':') p++;		*pr= cons(CELL,			p == env ? findword(".") : findnword(env, p-env));		pr= &(*pr)->cdr;		env= p;	} while (*env++ != 0);	return r;}void key_usage(char *how){	fprintf(stderr, "\"%s\", line %u: Usage: %s %s\n",		descr, pc->lineno, pc->line->car->name, how);	action= 0;}void inappropriate(void){	fprintf(stderr, "\"%s\", line %u: wrong execution phase for '%s'\n",		descr, pc->lineno, pc->line->car->name);	action= 0;}int readonly(cell_t *v){	if (v->flags & W_RDONLY) {		fprintf(stderr, "\"%s\", line %u: %s is read-only\n",			descr, pc->lineno, v->name);		action= 0;		return 1;	}	return 0;}void complain(cell_t *err)/* acd: err ... */{	cell_t *w;	fprintf(stderr, "%s:", program);	while (err != nil) {		if (err->type == CELL) {			w= err->car; err= err->cdr;		} else {			w= err; err= nil;		}		fprintf(stderr, " %s", w->name);	}	action= 0;}int keyword(char *name)/* True if the current line is headed by the given keyword. */{	cell_t *t;	return (t= pc->line) != nil && t->type == CELL		&& (t= t->car) != nil && t->type == WORD		&& strcmp(t->name, name) == 0;}cell_t *getvar(cell_t *v)/* Return a word or the word referenced by a subst. */{	if (v == nil) return nil;	if (v->type == WORD) return v;	if (v->type == SUBST) return v->subst;	return nil;}void argscan(void), compile(void);void transform(rule_t *);void exec_one(void)/* Execute one line of the program. */{	cell_t *v, *p, *q, *r, *t;	unsigned n= 0;	static int last_if= 1;	/* Description file this line came from. */	descr= pc->file->name;	for (p= pc->line; p != nil; p= p->cdr) n++;	if (n == 0) return;	/* Null statement. */	p= pc->line;	q= p->cdr;	r= q == nil ? nil : q->cdr;	/* Try one by one all the different commands. */	if (n >= 2 && q->car != nil && q->car->type == EQUALS) {		/* An assignment. */		int flags;		if ((v= getvar(p->car)) == nil) {			fprintf(stderr,				"\"%s\", line %u: Usage: <var> = expr ...\n",				descr, pc->lineno);			action= 0;			return;		}		if (readonly(v)) return;		flags= v->flags;		v->flags|= W_LOCAL|W_RDONLY;		t= evaluate(inc(r), PARTIAL);		dec(v->value);		v->value= t;		v->flags= flags | W_SET;		if (talk()) {			printf("%s =\b=\b= ", v->name);			prin2n(t);		}	} else	if (keyword("unset")) {		/* Set a variable to "undefined". */		if (n != 2 || (v= getvar(q->car)) == nil) {			key_usage("<var>");			return;		}		if (readonly(v)) return;		if (talk()) prin2n(p);		dec(v->value);		v->value= nil;		v->flags&= ~W_SET;	} else	if (keyword("import")) {		/* Import a variable from the UNIX environment. */		char *env;		if (n != 2 || (v= getvar(q->car)) == nil) {			key_usage("<var>");			return;		}		if (readonly(v)) return;		if ((env= getenv(v->name)) == nil) return;		if (talk()) printf("import %s=%s\n", v->name, env);		t= splitenv(env);		dec(v->value);		v->value= t;		v->flags|= W_SET;	} else	if (keyword("mktemp")) {		/* Assign a variable the name of a temporary file. */		char *tmp, *suff;		r= evaluate(inc(r), IMPLODE);		if (n == 3 && wordlist(&r, 1) != 1) n= 0;		if ((n != 2 && n != 3) || (v= getvar(q->car)) == nil) {			dec(r);			key_usage("<var> [<suffix>]");			return;		}		if (readonly(v)) { dec(r); return; }		tmp= maketemp();		suff= r == nil ? "" : r->name;		t= newcell();		t->type= WORD;		t->name= allocate(nil,			(strlen(tmp) + strlen(suff) + 1) * sizeof(*t->name));		strcpy(t->name, tmp);		strcat(t->name, suff);		t= inc(t);		dec(r);		dec(v->value);		v->value= t;		v->flags|= W_SET;		t->flags|= W_TEMP;		if (talk()) printf("mktemp %s=%s\n", v->name, t->name);	} else	if (keyword("temporary")) {		/* Mark a word as a temporary file. */		cell_t *tmp;		tmp= evaluate(inc(q), IMPLODE);		if (wordlist(&tmp, 1) < 0) {			dec(tmp);			key_usage("<word>");			return;		}		if (talk()) printf("temporary %s\n", tmp->name);		tmp->flags|= W_TEMP;		dec(tmp);	} else	if (keyword("stop")) {		/* Set the suffix to stop the transformation on. */		cell_t *suff;		if (phase > SCAN) { inappropriate(); return; }		suff= evaluate(inc(q), IMPLODE);		if (wordlist(&suff, 1) != 1) {			dec(suff);			key_usage("<suffix>");			return;		}		dec(V_stop);		V_stop= suff;		if (talk()) printf("stop %s\n", suff->name);	} else	if (keyword("numeric")) {		/* Check if a string denotes a number, like $n in -O$n. */		cell_t *num;		char *pn;		num= evaluate(inc(q), IMPLODE);		if (wordlist(&num, 1) != 1) {			dec(num);			key_usage("<arg>");			return;		}		if (talk()) printf("numeric %s\n", num->name);		(void) strtoul(num->name, &pn, 10);		if (*pn != 0) {			complain(phase == SCAN ? V_star->value : nil);			if (phase == SCAN) fputc(':', stderr);			fprintf(stderr, " '%s' is not a number\n", num->name);		}		dec(num);	} else	if (keyword("error")) {		/* Signal an error. */		cell_t *err;		err= evaluate(inc(q), IMPLODE);		if (wordlist(&err, 0) < 1) {			dec(err);			key_usage("expr ...");			return;		}		if (talk()) { printf("error "); prin2n(err); }		complain(err);		fputc('\n', stderr);		dec(err);	} else	if (keyword("if")) {		/* if (list) = (list) using set comparison. */		int eq;		if (n != 4 || r->car == nil || r->car->type != EQUALS) {			key_usage("<expr> = <expr>");			execute(DONT, pc->indent+1);			last_if= 1;			return;		}		q= q->car;		r= r->cdr->car;		if (talk()) {			printf("if ");			prin1(t= evaluate(inc(q), IMPLODE));			dec(t);			printf(" = ");			prin1n(t= evaluate(inc(r), IMPLODE));			dec(t);		}		eq= equal(q, r);		execute(eq ? DOIT : DONT, pc->indent+1);		last_if= eq;	} else	if (keyword("ifdef") || keyword("ifndef")) {		/* Is a variable defined or undefined? */		int doit;		if (n != 2 || (v= getvar(q->car)) == nil) {			key_usage("<var>");			execute(DONT, pc->indent+1);			last_if= 1;			return;		}		if (talk()) prin2n(p);		doit= ((v->flags & W_SET) != 0) ^ (p->car->name[2] == 'n');		execute(doit ? DOIT : DONT, pc->indent+1);		last_if= doit;	} else	if (keyword("iftemp") || keyword("ifhash")) {		/* Is a file a temporary file? */		/* Does a file need preprocessing? */		cell_t *file;		int doit= 0;		file= evaluate(inc(q), IMPLODE);		if (wordlist(&file, 1) != 1) {			dec(file);			key_usage("<arg>");			return;		}		if (talk()) printf("%s %s\n", p->car->name, file->name);		if (p->car->name[2] == 't') {			/* iftemp file */			if (file->flags & W_TEMP) doit= 1;		} else {			/* ifhash file */			int fd;			char hash;			if ((fd= open(file->name, O_RDONLY)) >= 0) {				if (read(fd, &hash, 1) == 1 && hash == '#')					doit= 1;				close(fd);			}		}		dec(file);		execute(doit ? DOIT : DONT, pc->indent+1);		last_if= doit;	} else	if (keyword("else")) {		/* Else clause for an if, ifdef, or ifndef. */		if (n != 1) {			key_usage("");			execute(DONT, pc->indent+1);			return;		}		if (talk()) prin2n(p);		execute(!last_if ? DOIT : DONT, pc->indent+1);	} else	if (keyword("treat")) {		/* Treat a file as having a certain suffix. */		if (phase > SCAN) { inappropriate(); return; }		if (n == 3) {			q= evaluate(inc(q->car), IMPLODE);			r= evaluate(inc(r->car), IMPLODE);		}		if (n != 3 || wordlist(&q, 1) != 1 || wordlist(&r, 1) != 1) {			if (n == 3) { dec(q); dec(r); }			key_usage("<file> <suffix>");			return;		}		if (talk()) printf("treat %s %s\n", q->name, r->name);		dec(q->suffix);		q->suffix= r;		q->flags|= W_SUFF;		dec(q);	} else	if (keyword("apply")) {		/* Apply a transformation rule to the current input file. */		rule_t *rule, *sav_path;		cell_t *sav_wait, *sav_in, *sav_out;		program_t *sav_next;		if (phase != COMPILE) { inappropriate(); return; }		if (V_star->value->cdr != nil) {			fprintf(stderr, "\"%s\", line %u: $* is not one file\n",				descr, pc->lineno);			action= 0;			return;		}		if (n == 3) {			q= evaluate(inc(q->car), IMPLODE);			r= evaluate(inc(r->car), IMPLODE);		}		if (n != 3 || wordlist(&q, 1) != 1 || wordlist(&r, 1) != 1) {			if (n == 3) { dec(q); dec(r); }			key_usage("<file> <suffix>");			return;		}		if (talk()) printf("apply %s %s\n", q->name, r->name);		/* Find a rule */		for (rule= rules; rule != nil; rule= rule->next) {			if (rule->type == TRANSFORM				&& rule->from == q && rule->to == r) break;		}		if (rule == nil) {			fprintf(stderr,				"\"%s\", line %u: no %s %s transformation\n",				descr, pc->lineno, q->name, r->name);			action= 0;		}		dec(q);		dec(r);		if (rule == nil) return;		/* Save the world. */		sav_path= rule->path;		sav_wait= rule->wait;		sav_in= V_in->value;		sav_out= V_out->value;		sav_next= nextpc;		/* Isolate the rule and give it new input. */		rule->path= rule;		rule->wait= V_star->value;		V_star->value= nil;		V_in->value= nil;		V_out->value= nil;		transform(rule);		/* Retrieve the new $* and repair. */		V_star->value= rule->wait;		rule->path= sav_path;		rule->wait= sav_wait;		V_in->value= sav_in;		V_out->value= sav_out;		V_out->flags= W_SET|W_LOCAL;		nextpc= sav_next;	} else	if (keyword("include")) {		/* Include another description file into this program. */		cell_t *file;		program_t *incl, *prog, **ppg= &prog;		file= evaluate(inc(q), IMPLODE);		if (wordlist(&file, 1) != 1) {			dec(file);			key_usage("<file>");			return;		}		if (talk()) printf("include %s\n", file->name);		descr= file->name;		incl= pc;		prog= get_prog();		dec(file);		/* Raise the program to the include's indent level. */		while (*ppg != nil) {			(*ppg)->indent += incl->indent;			ppg= &(*ppg)->next;		}		/* Kill the include and splice the included program in. */		dec(incl->line);		incl->line= nil;		*ppg= incl->next;		incl->next= prog;		pc= incl;		nextpc= prog;	} else	if (keyword("arg")) {		/* An argument scanning rule. */		if (phase > SCAN) { inappropriate(); return; }		if (n < 2) {			key_usage("<string> ...");			execute(DONT, pc->indent+1);			return;		}		if (talk()) prin2n(p);		newrule(ARG, inc(q), nil);		/* Always skip the body, it comes later. */		execute(DONT, pc->indent+1);	} else	if (keyword("transform")) {		/* A file transformation rule. */		if (phase > SCAN) { inappropriate(); return; }		if (n == 3) {			q= evaluate(inc(q->car), IMPLODE);			r= evaluate(inc(r->car), IMPLODE);		}		if (n != 3 || wordlist(&q, 1) != 1 || wordlist(&r, 1) != 1) {			if (n == 3) { dec(q); dec(r); }			key_usage("<suffix1> <suffix2>");			execute(DONT, pc->indent+1);			return;		}		if (talk()) printf("transform %s %s\n", q->name, r->name);		newrule(TRANSFORM, q, r);		/* Body comes later. */		execute(DONT, pc->indent+1);	} else	if (keyword("prefer")) {		/* Prefer a transformation over others. */		if (phase > SCAN) { inappropriate(); return; }		if (n == 3) {			q= evaluate(inc(q->car), IMPLODE);			r= evaluate(inc(r->car), IMPLODE);		}		if (n != 3 || wordlist(&q, 1) != 1 || wordlist(&r, 1) != 1) {			if (n == 3) { dec(q); dec(r); }			key_usage("<suffix1> <suffix2>");			return;		}		if (talk()) printf("prefer %s %s\n", q->name, r->name);		newrule(PREFER, q, r);	} else	if (keyword("combine")) {		/* A file combination (loader) rule. */		if (phase > SCAN) { inappropriate(); return; }		if (n == 3) {			q= evaluate(inc(q->car), IMPLODE);			r= evaluate(inc(r->car), IMPLODE);		}		if (n != 3 || wordlist(&q, 0) < 1 || wordlist(&r, 1) != 1) {			if (n == 3) { dec(q); dec(r); }			key_usage("<suffix-list> <suffix>");			execute(DONT, pc->indent+1);			return;		}		if (talk()) {			printf("combine ");			prin1(q);			printf(" %s\n", r->name);		}		newrule(COMBINE, q, r);		/* Body comes later. */		execute(DONT, pc->indent+1);	} else	if (keyword("scan") || keyword("compile")) {		program_t *next= nextpc;

⌨️ 快捷键说明

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