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

📄 make.c

📁 LSI C-86 compiler,小日本写的C语言编译器
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * make.c - a program for maintaining computer programs
 *	written by MORI, Koichiro (kmori@mixcosy)
 */

static char rcsID[] = "$Header: RCS/make.c 1.13 90/11/02 11:48:00 kmori Exp $";

/*
 * Compile switch
 *	-DOLDLSIFASHION		Set if '<' & '.PATH' required
 */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <time.h>
#include <dos.h>
#pragma	nonrec



char	Usage[] = "\
Make (C) 1987-1990 by MORI, Koichiro $Revision: 1.13 $\n\
Usage: make [options] [MACRO=value] [targets...]\n\
options:\n\
	-f FILE	read make command from file 'FILE'\n\
	-i	ignore return code\n\
	-k	make targets as many as possible\n\
	-n	do not execute; print what will be done\n\
	-r	do not use makedef\n\
	-s	do work silently\n\
	-t	only update timestamps\n\
";

typedef	char	bool;
#define	YES	1
#define	NO	0


typedef	struct command {
	struct command	*next;
	char		body[0];
} command;


typedef	struct	atom	{
	struct	atom	*next;
	char		*name;
	char		*macro;
	struct	list	*src;
	command		*commands;
	time_t		uptime;
	bool		visit;
	bool		userdef;
	char		type;
} ATOM;

typedef	struct	list	{
	struct	list	*next;
	struct	atom	*atom;
} LIST;



bool	Nflag, Tflag, Sflag, Iflag, Dflag, Kflag;	/* make options */

bool	Case;		/* true if differentiating upper/lower case */
bool	BsdMacro;	/* true if ${..} treated as macro expansion */



#define	MAXBACK	2048

FILE	*Mfp;
char	*Mfile;
int	Lineno;
char	Backs[MAXBACK];
char	*Backp = Backs;

#define	MAXNAME	100



#define	forall(x, y)	for ((x) = (y); (x) != NULL; (x) = (x)->next)



/*
 *
 */


void	error(char *p, char *str)
{
	fprintf(stderr, "make: ");
	if (Mfp != NULL)
		fprintf(stderr, "%s %d: ", Mfile, Lineno);
	fprintf(stderr, p, str);
	exit(1);
}



#define	new(t, n)	((t *)rawnew(sizeof(t) * (n)))
void	*rawnew(unsigned size)
{
	void	*p;

	if ((p = calloc(size, 1)) == NULL)
		error("out of memory\n", NULL);
	return (p);
}


int	cmpsym(char *s, char *t)
{
	if (Case)
		return (strcmp(s, t));
	for (; *s && tolower(*s) == tolower(*t); s++, t++)
		;
	return (*s - *t);
}






#define	NHASH	1024
static	ATOM	*Atoms[NHASH];

unsigned hash(char *s)
{
	unsigned n;

	n = 0;
	while (*s)
		n = n * 129 + tolower(*s++);
	return (n % NHASH);
}


ATOM	*lookup1(char *name, bool reg)
{
	ATOM	*a;
	char	*s;
	unsigned n;

	forall (a, Atoms[n = hash(name)]) {
		if (cmpsym(a->name, name) == 0)
			return (a);
	}
	if (*name != '.' && (s = getenv(name)) != NULL) {
		a = new(ATOM, 1);
		a->name = strcpy(new(char, strlen(name) + 1), name);
		a->next = Atoms[n];
		Atoms[n] = a;
		a->macro = s;
		return (a);
	}
	if (reg) {
		a = new(ATOM, 1);
		a->name = strcpy(new(char, strlen(name) + 1), name);
		a->next = Atoms[n];
		Atoms[n] = a;
		return (a);
	}
	return (NULL);
}

#define	lookup(name)	lookup1(name, 0)
#define	intern(name)	lookup1(name, 1)




/*
 *	Module get/put
 */

int	unget(int c)
{
	if (c == EOF)
		return (EOF);
	if (Backp >= Backs + MAXBACK)
		error("can't unget (maybe too long macro)\n", NULL);
	return (*Backp++ = c);
}


void	ungets(char *s)
{
	char	*p;

	for (p = s + strlen(s); --p >= s; )
		unget((int)*p);
}


int	quoget()
{
	int	c;

	if (Backp > Backs)
		return (*--Backp);
	if (Mfp == NULL)
		return (EOF);
	c = getc(Mfp);
	if (c == '\n')
		Lineno++;
}



static char Longmsg[] = "Too long identifier: %s...\n";


int	get()
{
	char	name[MAXNAME + 1];
	char	*p;
	int	c, term;
	ATOM	*m;

	for (;;) {
		if ((c = quoget()) != '$' || (c = quoget()) == '$')
			return (c);
		if (!BsdMacro && c == '{')
			return (-'{');
		if (c == '@' || c == '<' || c == '*' || c == '>' || c == '?' ||
			c == '#' || c == '&' || c == '[' || c == ':')
			return (-c);
		/* do macro evaluation */
		p = name;
		if (c == '(' || c == '{') {
			term = c == '(' ? ')' : '}';
			while ((c = quoget()) != term) {
				if (p >= name + MAXNAME) {
					*p = '\0';
					error(Longmsg, name);
				}
				*p++ = c;
			}
		}
		else if (!BsdMacro && (isalpha(c) || isdigit(c))) {
			while (isalpha(c) || isdigit(c)) {
				if (p >= name + MAXNAME) {
					*p = '\0';
					error(Longmsg, name);
				}
				*p++ = c;
				c = quoget();
			}
			unget(c);
		}
		else
			*p++ = c;
		*p = '\0';
		if ((m = lookup(name)) != NULL && m->macro != NULL)
			ungets(m->macro);
	}
}


/*
 */


	static	ATOM	*Backtok = NULL;


bool	isbreak(int c)
{
	return (c == ' ' || c == '\t' || c == '\n' ||
		c == EOF || c == '=' || c == '#' || c == '<');
}

bool	ColonBreak = NO;

ATOM	*gettok()
{
	char	buf[MAXNAME + 1];
	char	*p;
	int	c, b;
	ATOM	*a;

	if ((a = Backtok) != NULL) {
		Backtok = NULL;
		return (a);
	}
	for (;;) {
		while ((c = get()) == ' ' || c == '\t')
			;
		if (c != '\\')
			break;
		if ((b = get()) != '\n') {
			unget(b);
			break;
		}
	}
	if (c == '#')
		while ((c = quoget()) != '\n' && c != EOF)
			;
	p = buf;
	if (c == EOF)
		return (NULL);
	else if (c == '\n' || c == ':' || c == '=' || c == '<' || c == ';')
		*p++ = c;
	else {
		while (! isbreak(c)) {
			if (c == ':' && ColonBreak && isbreak(unget(get())))
				break;
			if (p >= buf + MAXNAME) {
				*p = '\0';
				error(Longmsg, buf);
			}
			*p++ = c;
			c = get();
		}
		unget(c);
	}
	*p = '\0';
	return (intern(buf));
}



void	ungettok(ATOM *a)
{
	if (Backtok != NULL)
		error("can't ungettok\n", NULL);
	Backtok = a;
}



/* reserve some keywords */

ATOM	*NEWLINE, *EQUAL, *COLON, *LESS, *SEMICOLON,
	*SUFFIXES, *IGNORE, *SILENT, *MFLAGS, *MAKE, *CASE, *MACRO;

void	initgettok()
{
	NEWLINE	= intern("\n");
	EQUAL	= intern("=");
	COLON	= intern(":");
	LESS	= intern("<");
	SEMICOLON = intern(";");
	SUFFIXES = intern(".SUFFIXES");
	IGNORE = intern(".IGNORE");
	SILENT = intern(".SILENT");
	CASE = intern(".CASE");
	MACRO = intern(".MACRO");
	MFLAGS = intern("MFLAGS");
	MAKE = intern("MAKE");
}





LIST	*cons(ATOM *atom, LIST *next)
{
	LIST	*l;

	l = new(LIST, 1);
	l->next = next;
	l->atom = atom;
	return (l);
}

recursive LIST	*append(LIST *x, LIST *y)
{
	return (x == NULL ? y : cons(x->atom, append(x->next, y)));
}


recursive LIST	*getlist()
{
	ATOM	*s;

	if ((s = gettok()) == NULL || s == NEWLINE ||
		s == LESS || s == EQUAL || s == COLON || s == SEMICOLON) {
		ungettok(s);
		return (NULL);
	}
	return (cons(s, getlist()));
}


static	char	Lines[2048];

command	*getcom(ATOM *t)
{
	int	c;
	char	*s;
	command	*p, *q;

	p = NULL;
	for (;;) {
		c = quoget();
		if (c == '#') {
			while ((c = quoget()) != '\n' && c != EOF)
				;
			continue;
		} else if (t != SEMICOLON && c != '\t')
			break;
		t = NULL;
		while (c == ' ' || c == '\t')
			c = quoget();
		s = Lines;
		while (c != '\n' && c != EOF) {
			*s++ = c;
			c = quoget();
		}
		*s++ = '\n';
		*s++ = '\0';
		q = rawnew(sizeof(command) + (s - Lines));
		strcpy(q->body, Lines);
		q->next = p;
		p = q;
	}
	unget(c);
	return (p);
}


char	*getline()
{
	int	c;
	char	*s;

	while ((c = quoget()) == ' ' || c == '\t')
		;
	s = Lines;
	while (c != '\n' && c != EOF) {
		*s = c;
		c = quoget();
		if (*s == '\\' && c == '\n') {
			while ((c = quoget()) == ' ' || c == '\t')
				;
		} else {
			s++;
		}
	}
	*s++ = '\0';
	return (strcpy(new(char, s - Lines), Lines));
}


bool	exist(char *file)
{
	int	fd;

	if ((fd = open(file, 0)) < 0)
		return (NO);
	close(fd);
	return (YES);
}

time_t	timeof(ATOM *file)
{
	time_t	times[2];

	if (file->uptime != 0)
		return (file->uptime);
	if (gftime(file->name, times))
		return (0);
	return (file->uptime = times[1]);
}


void	touch(ATOM *file)
{
	time_t	times[2];

	file->uptime = times[0] = times[1] = time(0);
	utime(file->name, times);
}



void	setcommand(ATOM *atom, command *com)
{
	if (com == NULL)
		return;
	if (atom->name[0] != '.' &&
		atom->commands != NULL && atom->commands != com)
		error("2 or more commands for '%s'\n", atom->name);
	atom->commands = com;
}


ATOM	*readmake(char *fn)
{
	ATOM	*a, *deftar;
	LIST	*l, *r, *f;
	char	type;
	command	*com;
	char	*mac;

	errno = 0;
	Mfile = fn;
	Lineno = 1;
	if (strcmp(fn, "-") == 0)
		Mfp = stdin;
	else
		if ((Mfp = fopen(fn, "r")) == NULL)
			return (NULL);
	deftar = NULL;
	ColonBreak = YES;
	while ((a = gettok()) != NULL) {
		if (a == NEWLINE)
			continue;
		ungettok(a);
		l = getlist();
		if ((type = ':', (a = gettok()) == COLON) ||
			(type = '<', a == LESS)) {
		/* dependency line */
			ColonBreak = NO;
			r = getlist();
			ColonBreak = YES;
			if ((a = gettok()) != NEWLINE && a != SEMICOLON)
				error("bad delimiter: '%s'\n", a->name);
			com = getcom(a);
			forall (f, l) {
				if (f->atom == SILENT)
					Sflag = YES;
				else if (f->atom ==  IGNORE)
					Iflag = YES;
				else if (f->atom == SUFFIXES && r == NULL)
					f->atom->src = NULL;
				else if (f->atom == CASE)
					Case = YES;
				else if (f->atom == MACRO)
					BsdMacro = YES;
				setcommand(f->atom, com);
				f->atom->src = append(f->atom->src, r);
				if (deftar == NULL && f->atom->name[0] != '.')
					deftar = f->atom;
				f->atom->type = type;
			}
		} else if (a == EQUAL) {
		/* macro definition */
			mac = getline();
			forall (f, l)
				if (! f->atom->userdef)
					f->atom->macro = mac;
		} else
			error("missing ':' after '%s'\n", l->atom->name);
	}
	fclose(Mfp);
	Mfp = NULL;
	return (deftar);
}


char	*suffix(char *s)
{
	char	*p;

	p = NULL;
	while (*s) {
		if (*s == '.')
			p = s;
		s++;
	}
	return (p ? p : s);
}


char	*prefix(char *buf, char *s)
{
	char	*p, *d;

	p = suffix(s);
	d = buf;
	while (s < p)
		*d++ = *s++;
	*d = '\0';
	return (buf);
}


char	*barename(char *s)
{
	char	*p, c;

	p = s;
	while (c = *p++)
		if (c == ':' || c == '\\' || c == '/')
			s = p;
	return (s);
}


void	complete_unix(ATOM *tar)	/* complete commands */
{
	LIST	*l;
#ifdef	OLDLSIFASHION
	LIST	*m;
#endif

⌨️ 快捷键说明

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