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

📄 marshal.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
		if(out + 4 >= e)			goto exhausted;		*out++ = t64e[(b24>>18)];		*out++ = t64e[(b24>>12)&0x3f];		*out++ = '=';		break;	case 0:		if((i%18) != 0)			*out++ = '\n';		*out = 0;		return out - start;	}exhausted:	*out++ = '=';	*out++ = '\n';	*out = 0;	return out - start;}voidfreealias(Alias *a){	freeaddrs(a->addr);	free(a);}voidfreealiases(Alias *a){	Alias *next;	while(a != nil){		next = a->next;		freealias(a);		a = next;	}}////  read alias file//Alias*readaliases(void){	Alias *a, **l, *first;	Addr *addr, **al;	String *file, *line, *token;	static int already;	Sinstack *sp;	first = nil;	file = s_new();	line = s_new();	token = s_new();	// open and get length	mboxpath("names", login, file, 0);	sp = s_allocinstack(s_to_c(file));	if(sp == nil)		goto out;	l = &first;	// read a line at a time.	while(s_rdinstack(sp, s_restart(line))!=nil) {		s_restart(line);		a = emalloc(sizeof(Alias));		al = &a->addr;		for(;;){			if(s_parse(line, s_restart(token))==0)				break;			addr = emalloc(sizeof(Addr));			addr->v = strdup(s_to_c(token));			addr->next = 0;			*al = addr;			al = &addr->next;		} 		if(a->addr == nil || a->addr->next == nil){			freealias(a);			continue;		}		a->next = nil;		*l = a;		l = &a->next;	}	s_freeinstack(sp);out:	s_free(file);	s_free(line);	s_free(token);	return first;}Addr*newaddr(char *name){	Addr *a;	a = emalloc(sizeof(*a));	a->next = nil;	a->v = estrdup(name);	if(a->v == nil)		sysfatal("%r");	return a;}////  expand personal aliases since the names are meaningless in//  other contexts//Addr*_expand(Addr *old, int *changedp){	Alias *al;	Addr *first, *next, **l, *a;	*changedp = 0;	first = nil;	l = &first;	for(;old != nil; old = next){		next = old->next;		for(al = aliases; al != nil; al = al->next){			if(strcmp(al->addr->v, old->v) == 0){				for(a = al->addr->next; a != nil; a = a->next){					*l = newaddr(a->v);					if(*l == nil)						sysfatal("%r");					l = &(*l)->next;					*changedp = 1;				}				break;			}		}		if(al != nil){			freeaddr(old);			continue;		}		*l = old;		old->next = nil;		l = &(*l)->next;	}	return first;}Addr*rexpand(Addr *old){	int i, changed;	changed = 0;	for(i=0; i<32; i++){		old = _expand(old, &changed);		if(changed == 0)			break;	}	return old;}Addr*unique(Addr *first){	Addr *a, **l, *x;	for(a = first; a != nil; a = a->next){		for(l = &a->next; *l != nil;){			if(strcmp(a->v, (*l)->v) == 0){				x = *l;				*l = x->next;				freeaddr(x);			} else				l = &(*l)->next;		}	}	return first;}Addr*expand(int ac, char **av){	Addr *first, **l;	int i;	first = nil;	// make a list of the starting addresses	l = &first;	for(i = 0; i < ac; i++){		*l = newaddr(av[i]);		if(*l == nil)			sysfatal("%r");		l = &(*l)->next;	}	// recurse till we don't change any more	return unique(rexpand(first));}Addr*concataddr(Addr *a, Addr *b){	Addr *oa;	if(a == nil)		return b;	oa = a;	for(; a->next; a=a->next)		;	a->next = b;	return oa;}voidfreeaddr(Addr *ap){	free(ap->v);	free(ap);}voidfreeaddrs(Addr *ap){	Addr *next;	for(; ap; ap=next) {		next = ap->next;		freeaddr(ap);	}}String*s_copyn(char *s, int n){	return s_nappend(s_reset(nil), s, n);}// fetch the next token from an RFC822 address string// we assume the header is RFC822-conformant in that// we recognize escaping anywhere even though it is only// supposed to be in quoted-strings, domain-literals, and comments.//// i'd use yylex or yyparse here, but we need to preserve // things like comments, which i think it tosses away.//// we're not strictly RFC822 compliant.  we misparse such nonsense as////	To: gre @ (Grace) plan9 . (Emlin) bell-labs.com//// make sure there's no whitespace in your addresses and // you'll be fine.//enum {	Twhite,	Tcomment,	Twords,	Tcomma,	Tleftangle,	Trightangle,	Terror,	Tend,};//char *ty82[] = {"white", "comment", "words", "comma", "<", ">", "err", "end"};#define ISWHITE(p) ((p)==' ' || (p)=='\t' || (p)=='\n' || (p)=='\r')intget822token(String **tok, char *p, char **pp){	char *op;	int type;	int quoting;	op = p;	switch(*p){	case '\0':		*tok = nil;		*pp = nil;		return Tend;	case ' ':	// get whitespace	case '\t':	case '\n':	case '\r':		type = Twhite;		while(ISWHITE(*p))			p++;		break;	case '(':	// get comment		type = Tcomment;		for(p++; *p && *p != ')'; p++)			if(*p == '\\') {				if(*(p+1) == '\0') {					*tok = nil;					return Terror;				}				p++;			}		if(*p != ')') {			*tok = nil;			return Terror;		}		p++;		break;	case ',':		type = Tcomma;		p++;		break;	case '<':		type = Tleftangle;		p++;		break;	case '>':		type = Trightangle;		p++;		break;	default:	// bunch of letters, perhaps quoted strings tossed in		type = Twords;		quoting = 0;		for(; *p && (quoting || (!ISWHITE(*p) && *p != '>' && *p != '<' && *p != ',')); p++) {			if(*p == '"') 				quoting = !quoting;			if(*p == '\\') {				if(*(p+1) == '\0') {					*tok = nil;					return Terror;				}				p++;			}		}		break;	}	if(pp)		*pp = p;	*tok = s_copyn(op, p-op);	return type;}	// expand local aliases in an RFC822 mail line// add list of expanded addresses to to.Addr*expandline(String **s, Addr *to){	Addr *na, *nto, *ap;	char *p;	int tok, inangle, hadangle, nword;	String *os, *ns, *stok, *lastword, *sinceword;	os = s_copy(s_to_c(*s));	p = strchr(s_to_c(*s), ':');	assert(p != nil);	p++;	ns = s_copyn(s_to_c(*s), p-s_to_c(*s));	stok = nil;	nto = nil;	//	// the only valid mailbox namings are word	// and word* < addr >	// without comments this would be simple.	// we keep the following:	//	lastword - current guess at the address	//	sinceword - whitespace and comment seen since lastword	//	lastword = s_new();	sinceword = s_new();	inangle = 0;	nword = 0;	hadangle = 0;	for(;;) {		stok = nil;		switch(tok = get822token(&stok, p, &p)){		default:			abort();		case Tcomma:		case Tend:			if(inangle)				goto Error;			if(nword != 1)				goto Error;			na = rexpand(newaddr(s_to_c(lastword)));			s_append(ns, na->v);			s_append(ns, s_to_c(sinceword));			for(ap=na->next; ap; ap=ap->next) {				s_append(ns, ", ");				s_append(ns, ap->v);			}			nto = concataddr(na, nto);			if(tok == Tcomma){				s_append(ns, ",");				s_free(stok);			}			if(tok == Tend)				goto Break2;			inangle = 0;			nword = 0;			hadangle = 0;			s_reset(sinceword);			s_reset(lastword);			break;		case Twhite:		case Tcomment:			s_append(sinceword, s_to_c(stok));			s_free(stok);			break;		case Trightangle:			if(!inangle)				goto Error;			inangle = 0;			hadangle = 1;			s_append(sinceword, s_to_c(stok));			s_free(stok);			break;		case Twords:		case Tleftangle:			if(hadangle)				goto Error;			if(tok != Tleftangle && inangle && s_len(lastword))				goto Error;			if(tok == Tleftangle) {				inangle = 1;				nword = 1;			}			s_append(ns, s_to_c(lastword));			s_append(ns, s_to_c(sinceword));			s_reset(sinceword);			if(tok == Tleftangle) {				s_append(ns, "<");				s_reset(lastword);			} else {				s_free(lastword);				lastword = stok;			}			if(!inangle)				nword++;			break;		case Terror:	// give up, use old string, addrs		Error:			ns = os;			os = nil;			freeaddrs(nto);			nto = nil;			werrstr("rfc822 syntax error");			rfc822syntaxerror = 1;			goto Break2;					}	}Break2:	s_free(*s);	s_free(os);	*s = ns;	nto = concataddr(nto, to);	return nto;}voidBdrain(Biobuf *b){	char buf[8192];	while(Bread(b, buf, sizeof buf) > 0)		;}voidreadmimetypes(void){	Biobuf *b;	char *p;	char *f[6];	char type[256];	static int alloced, inuse;	if(mimetypes == 0){		alloced = 256;		mimetypes = emalloc(alloced*sizeof(Ctype));		mimetypes[0].ext = "";	}	b = Bopen("/sys/lib/mimetype", OREAD);	if(b == nil)		return;	for(;;){		p = Brdline(b, '\n');		if(p == nil)			break;		p[Blinelen(b)-1] = 0;		if(tokenize(p, f, 6) < 4)			continue;		if(strcmp(f[0], "-") == 0 || strcmp(f[1], "-") == 0 || strcmp(f[2], "-") == 0)			continue;		if(inuse + 1 >= alloced){			alloced += 256;			mimetypes = erealloc(mimetypes, alloced*sizeof(Ctype));		}		snprint(type, sizeof(type), "%s/%s", f[1], f[2]);		mimetypes[inuse].type = estrdup(type);		mimetypes[inuse].ext = estrdup(f[0]+1);		mimetypes[inuse].display = !strcmp(type, "text/plain");		inuse++;		// always make sure there's a terminator		mimetypes[inuse].ext = 0;	}	Bterm(b);}char*estrdup(char *x){	x = strdup(x);	if(x == nil)		fatal("memory");	return x;}void*emalloc(int n){	void *x;	x = malloc(n);	if(x == nil)		fatal("%r");	return x;}void*erealloc(void *x, int n){	x = realloc(x, n);	if(x == nil)		fatal("%r");	return x;}//// Formatter for %"// Use double quotes to protect white space, frogs, \ and "//enum{	Qok = 0,	Qquote,	Qbackslash,};static intneedtoquote(Rune r){	if(r >= Runeself)		return Qquote;	if(r <= ' ')		return Qquote;	if(r=='\\' || r=='"')		return Qbackslash;	return Qok;}intdoublequote(Fmt *f){	char *s, *t;	int w, quotes;	Rune r;	s = va_arg(f->args, char*);	if(s == nil || *s == '\0')		return fmtstrcpy(f, "\"\"");	quotes = 0;	for(t=s; *t; t+=w){		w = chartorune(&r, t);		quotes |= needtoquote(r);	}	if(quotes == 0)		return fmtstrcpy(f, s);	fmtrune(f, '"');	for(t=s; *t; t+=w){		w = chartorune(&r, t);		if(needtoquote(r) == Qbackslash)			fmtrune(f, '\\');		fmtrune(f, r);	}	return fmtrune(f, '"');}intrfc2047fmt(Fmt *fmt){	char *s, *p;	s = va_arg(fmt->args, char*);	if(s == nil)		return fmtstrcpy(fmt, "");	for(p=s; *p; p++)		if((uchar)*p >= 0x80)			goto hard;	return fmtstrcpy(fmt, s);hard:	fmtprint(fmt, "=?utf-8?q?");	for(p=s; *p; p++){		if(*p == ' ')			fmtrune(fmt, '_');		else if(*p == '_' || *p == '\t' || *p == '=' || *p == '?' || (uchar)*p >= 0x80)			fmtprint(fmt, "=%.2uX", (uchar)*p);		else			fmtrune(fmt, (uchar)*p);	}				fmtprint(fmt, "?=");	return 0;}char*mksubject(char *line){	char *p, *q;	static char buf[1024];	p = strchr(line, ':')+1;	while(*p == ' ')		p++;	for(q=p; *q; q++)		if((uchar)*q >= 0x80)			goto hard;	return line;hard:	snprint(buf, sizeof buf, "Subject: %U", p);	return buf;}

⌨️ 快捷键说明

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