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

📄 imap4d.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
	return f;}/* * flags	: flag | flags ' ' flag * flag		: '\' atom | atom */static intflags(void){	int ff, flags;	char *s;	int c;	flags = 0;	for(;;){		c = peekc();		if(c == '\\'){			mustBe('\\');			s = atomString(atomStop, "\\");		}else if(strchr(atomStop, c) != nil)			s = atom();		else			break;		ff = mapFlag(s);		if(ff == 0)			parseErr("flag not supported");		flags |= ff;		if(peekc() != ' ')			break;		mustBe(' ');	}	if(flags == 0)		parseErr("no flags given");	return flags;}/* * storeWhat	: osign 'FLAGS' ' ' storeflags *		| osign 'FLAGS.SILENT' ' ' storeflags * osign	: *		| '+' | '-' * storeflags	: flagList | flags */static Store*storeWhat(void){	int f;	char *s;	int c, w;	c = peekc();	if(c == '+' || c == '-')		mustBe(c);	else		c = 0;	s = atom();	w = 0;	if(cistrcmp(s, "flags") == 0)		w = STFlags;	else if(cistrcmp(s, "flags.silent") == 0)		w = STFlagsSilent;	else		parseErr("illegal store attribute");	mustBe(' ');	if(peekc() == '(')		f = flagList();	else		f = flags();	return mkStore(c, w, f);}/* * fetchWhat	: "ALL" | "FULL" | "FAST" | fetchAtt | '(' fetchAtts ')' * fetchAtts	: fetchAtt | fetchAtts ' ' fetchAtt */static char *fetchAtom	= "(){}%*\"\\[]";static Fetch*fetchWhat(void){	Fetch *f;	char *s;	if(peekc() == '('){		getc();		f = nil;		for(;;){			s = atomString(fetchAtom, "");			f = fetchAtt(s, f);			if(peekc() == ')')				break;			mustBe(' ');		}		getc();		return revFetch(f);	}	s = atomString(fetchAtom, "");	if(cistrcmp(s, "all") == 0)		f = mkFetch(FFlags, mkFetch(FInternalDate, mkFetch(FRfc822Size, mkFetch(FEnvelope, nil))));	else if(cistrcmp(s, "fast") == 0)		f = mkFetch(FFlags, mkFetch(FInternalDate, mkFetch(FRfc822Size, nil)));	else if(cistrcmp(s, "full") == 0)		f = mkFetch(FFlags, mkFetch(FInternalDate, mkFetch(FRfc822Size, mkFetch(FEnvelope, mkFetch(FBody, nil)))));	else		f = fetchAtt(s, nil);	return f;}/* * fetchAtt	: "ENVELOPE" | "FLAGS" | "INTERNALDATE" *		| "RFC822" | "RFC822.HEADER" | "RFC822.SIZE" | "RFC822.TEXT" *		| "BODYSTRUCTURE" *		| "UID" *		| "BODY" *		| "BODY" bodysubs *		| "BODY.PEEK" bodysubs * bodysubs	: sect *		| sect '<' number '.' nz-number '>' * sect		: '[' sectSpec ']' * sectSpec	: sectMsgText *		| sectPart *		| sectPart '.' sectText * sectPart	: nz-number *		| sectPart '.' nz-number */static Fetch*fetchAtt(char *s, Fetch *f){	NList *sect;	int c;	if(cistrcmp(s, "envelope") == 0)		return mkFetch(FEnvelope, f);	if(cistrcmp(s, "flags") == 0)		return mkFetch(FFlags, f);	if(cistrcmp(s, "internaldate") == 0)		return mkFetch(FInternalDate, f);	if(cistrcmp(s, "RFC822") == 0)		return mkFetch(FRfc822, f);	if(cistrcmp(s, "RFC822.header") == 0)		return mkFetch(FRfc822Head, f);	if(cistrcmp(s, "RFC822.size") == 0)		return mkFetch(FRfc822Size, f);	if(cistrcmp(s, "RFC822.text") == 0)		return mkFetch(FRfc822Text, f);	if(cistrcmp(s, "bodystructure") == 0)		return mkFetch(FBodyStruct, f);	if(cistrcmp(s, "uid") == 0)		return mkFetch(FUid, f);	if(cistrcmp(s, "body") == 0){		if(peekc() != '[')			return mkFetch(FBody, f);		f = mkFetch(FBodySect, f);	}else if(cistrcmp(s, "body.peek") == 0)		f = mkFetch(FBodyPeek, f);	else		parseErr("illegal fetch attribute");	mustBe('[');	c = peekc();	if(c >= '1' && c <= '9'){		sect = mkNList(number(1), nil);		while(peekc() == '.'){			getc();			c = peekc();			if(c >= '1' && c <= '9'){				sect = mkNList(number(1), sect);			}else{				break;			}		}		f->sect = revNList(sect);	}	if(peekc() != ']')		sectText(f, f->sect != nil);	mustBe(']');	if(peekc() != '<')		return f;	f->partial = 1;	mustBe('<');	f->start = number(0);	mustBe('.');	f->size = number(1);	mustBe('>');	return f;}/* * sectText	: sectMsgText | "MIME" * sectMsgText	: "HEADER" *		| "TEXT" *		| "HEADER.FIELDS" ' ' hdrList *		| "HEADER.FIELDS.NOT" ' ' hdrList * hdrList	: '(' hdrs ')' * hdrs:	: astring *		| hdrs ' ' astring */static voidsectText(Fetch *f, int mimeOk){	SList *h;	char *s;	s = atomString(fetchAtom, "");	if(cistrcmp(s, "header") == 0){		f->part = FPHead;		return;	}	if(cistrcmp(s, "text") == 0){		f->part = FPText;		return;	}	if(mimeOk && cistrcmp(s, "mime") == 0){		f->part = FPMime;		return;	}	if(cistrcmp(s, "header.fields") == 0)		f->part = FPHeadFields;	else if(cistrcmp(s, "header.fields.not") == 0)		f->part = FPHeadFieldsNot;	else		parseErr("illegal fetch section text");	mustBe(' ');	mustBe('(');	h = nil;	for(;;){		h = mkSList(astring(), h);		if(peekc() == ')')			break;		mustBe(' ');	}	mustBe(')');	f->hdrs = revSList(h);}/* * searchWhat	: "CHARSET" ' ' astring searchkeys | searchkeys * searchkeys	: searchkey | searchkeys ' ' searchkey * searchkey	: "ALL" | "ANSWERED" | "DELETED" | "FLAGGED" | "NEW" | "OLD" | "RECENT" *		| "SEEN" | "UNANSWERED" | "UNDELETED" | "UNFLAGGED" | "DRAFT" | "UNDRAFT" *		| astrkey ' ' astring *		| datekey ' ' date *		| "KEYWORD" ' ' flag | "UNKEYWORD" flag *		| "LARGER" ' ' number | "SMALLER" ' ' number * 		| "HEADER" astring ' ' astring *		| set | "UID" ' ' set *		| "NOT" ' ' searchkey *		| "OR" ' ' searchkey ' ' searchkey *		| '(' searchkeys ')' * astrkey	: "BCC" | "BODY" | "CC" | "FROM" | "SUBJECT" | "TEXT" | "TO" * datekey	: "BEFORE" | "ON" | "SINCE" | "SENTBEFORE" | "SENTON" | "SENTSINCE" */static NamedInt searchMap[] ={	{"ALL",		SKAll},	{"ANSWERED",	SKAnswered},	{"DELETED",	SKDeleted},	{"FLAGGED",	SKFlagged},	{"NEW",		SKNew},	{"OLD",		SKOld},	{"RECENT",	SKRecent},	{"SEEN",	SKSeen},	{"UNANSWERED",	SKUnanswered},	{"UNDELETED",	SKUndeleted},	{"UNFLAGGED",	SKUnflagged},	{"DRAFT",	SKDraft},	{"UNDRAFT",	SKUndraft},	{"UNSEEN",	SKUnseen},	{nil,		0}};static NamedInt searchMapStr[] ={	{"CHARSET",	SKCharset},	{"BCC",		SKBcc},	{"BODY",	SKBody},	{"CC",		SKCc},	{"FROM",	SKFrom},	{"SUBJECT",	SKSubject},	{"TEXT",	SKText},	{"TO",		SKTo},	{nil,		0}};static NamedInt searchMapDate[] ={	{"BEFORE",	SKBefore},	{"ON",		SKOn},	{"SINCE",	SKSince},	{"SENTBEFORE",	SKSentBefore},	{"SENTON",	SKSentOn},	{"SENTSINCE",	SKSentSince},	{nil,		0}};static NamedInt searchMapFlag[] ={	{"KEYWORD",	SKKeyword},	{"UNKEYWORD",	SKUnkeyword},	{nil,		0}};static NamedInt searchMapNum[] ={	{"SMALLER",	SKSmaller},	{"LARGER",	SKLarger},	{nil,		0}};static Search*searchKeys(int first, Search *tail){	Search *s;	for(;;){		if(peekc() == '('){			getc();			tail = searchKeys(0, tail);			mustBe(')');		}else{			s = searchKey(first);			tail->next = s;			tail = s;		}		first = 0;		if(peekc() != ' ')			break;		getc();	}	return tail;}static Search*searchKey(int first){	Search *sr, rock;	Tm tm;	char *a;	int i, c;	sr = binalloc(&parseBin, sizeof(Search), 1);	if(sr == nil)		parseErr("out of memory");	c = peekc();	if(c >= '0' && c <= '9'){		sr->key = SKSet;		sr->set = msgSet(0);		return sr;	}	a = atom();	if(i = mapInt(searchMap, a))		sr->key = i;	else if(i = mapInt(searchMapStr, a)){		if(!first && i == SKCharset)			parseErr("illegal search key");		sr->key = i;		mustBe(' ');		sr->s = astring();	}else if(i = mapInt(searchMapDate, a)){		sr->key = i;		mustBe(' ');		c = peekc();		if(c == '"')			getc();		a = atom();		if(!imap4Date(&tm, a))			parseErr("bad date format");		sr->year = tm.year;		sr->mon = tm.mon;		sr->mday = tm.mday;		if(c == '"')			mustBe('"');	}else if(i = mapInt(searchMapFlag, a)){		sr->key = i;		mustBe(' ');		c = peekc();		if(c == '\\'){			mustBe('\\');			a = atomString(atomStop, "\\");		}else			a = atom();		i = mapFlag(a);		if(i == 0)			parseErr("flag not supported");		sr->num = i;	}else if(i = mapInt(searchMapNum, a)){		sr->key = i;		mustBe(' ');		sr->num = number(0);	}else if(cistrcmp(a, "HEADER") == 0){		sr->key = SKHeader;		mustBe(' ');		sr->hdr = astring();		mustBe(' ');		sr->s = astring();	}else if(cistrcmp(a, "UID") == 0){		sr->key = SKUid;		mustBe(' ');		sr->set = msgSet(0);	}else if(cistrcmp(a, "NOT") == 0){		sr->key = SKNot;		mustBe(' ');		rock.next = nil;		searchKeys(0, &rock);		sr->left = rock.next;	}else if(cistrcmp(a, "OR") == 0){		sr->key = SKOr;		mustBe(' ');		rock.next = nil;		searchKeys(0, &rock);		sr->left = rock.next;		mustBe(' ');		rock.next = nil;		searchKeys(0, &rock);		sr->right = rock.next;	}else		parseErr("illegal search key");	return sr;}/* * set	: seqno *	| seqno ':' seqno *	| set ',' set * seqno: nz-number *	| '*' * */static MsgSet*msgSet(int uids){	MsgSet head, *last, *ms;	ulong from, to;	last = &head;	head.next = nil;	for(;;){		from = uids ? uidNo() : seqNo();		to = from;		if(peekc() == ':'){			getc();			to = uids ? uidNo() : seqNo();		}		ms = binalloc(&parseBin, sizeof(MsgSet), 0);		if(ms == nil)			parseErr("out of memory");		ms->from = from;		ms->to = to;		ms->next = nil;		last->next = ms;		last = ms;		if(peekc() != ',')			break;		getc();	}	return head.next;}static ulongseqNo(void){	if(peekc() == '*'){		getc();		return ~0UL;	}	return number(1);}static ulonguidNo(void){	if(peekc() == '*'){		getc();		return ~0UL;	}	return number(0);}/* * 7 bit, non-ctl chars, no (){%*"\ * NIL is special case for nstring or parenlist */static char *atom(void){	return atomString(atomStop, "");}/* * like an atom, but no + */static char *tag(void){	return atomString("+(){%*\"\\", "");}/* * string or atom allowing %* */static char *listmbox(void){	int c;	c = peekc();	if(c == '{')		return literal();	if(c == '"')		return quoted();	return atomString("(){\"\\", "");}/* * string or atom */static char *astring(void){	int c;	c = peekc();	if(c == '{')		return literal();	if(c == '"')		return quoted();	return atom();}/* * 7 bit, non-ctl chars, none from exception list */static char *atomString(char *disallowed, char *initial){	char *s;	int c, ns, as;	ns = strlen(initial);	s = binalloc(&parseBin, ns + StrAlloc, 0);	if(s == nil)		parseErr("out of memory");	strcpy(s, initial);	as = ns + StrAlloc;	for(;;){		c = getc();		if(c <= ' ' || c >= 0x7f || strchr(disallowed, c) != nil){			ungetc();			break;		}		s[ns++] = c;		if(ns >= as){			s = bingrow(&parseBin, s, as, as + StrAlloc, 0);			if(s == nil)				parseErr("out of memory");			as += StrAlloc;		}	}	if(ns == 0)		badsyn();	s[ns] = '\0';	return s;}/* * quoted: '"' chars* '"' * chars:	1-128 except \r and \n */static char *quoted(void){	char *s;	int c, ns, as;	mustBe('"');	s = binalloc(&parseBin, StrAlloc, 0);	if(s == nil)		parseErr("out of memory");	as = StrAlloc;	ns = 0;	for(;;){		c = getc();		if(c == '"')			break;		if(c < 1 || c > 0x7f || c == '\r' || c == '\n')			badsyn();		if(c == '\\'){			c = getc();			if(c != '\\' && c != '"')				badsyn();		}		s[ns++] = c;		if(ns >= as){			s = bingrow(&parseBin, s, as, as + StrAlloc, 0);			if(s == nil)				parseErr("out of memory");			as += StrAlloc;		}	}	s[ns] = '\0';	return s;}/* * litlen: {number}\r\n */static ulonglitlen(void){	ulong v;	mustBe('{');	v = number(0);	mustBe('}');	crnl();	return v;}/* * literal: litlen data<0:litlen> */static char *literal(void){	char *s;	ulong v;	v = litlen();	s = binalloc(&parseBin, v+1, 0);	if(s == nil)		parseErr("out of memory");	Bprint(&bout, "+ Ready for literal data\r\n");	if(Bflush(&bout) < 0)		writeErr();	if(v != 0 && Bread(&bin, s, v) != v)		badsyn();	s[v] = '\0';	return s;}/* * digits; number is 32 bits */static ulongnumber(int nonzero){	ulong v;	int c, first;	v = 0;	first = 1;	for(;;){		c = getc();		if(c < '0' || c > '9'){			ungetc();			if(first)				badsyn();			break;		}		if(nonzero && first && c == '0')			badsyn();		c -= '0';		first = 0;		if(v > UlongMax/10 || v == UlongMax/10 && c > UlongMax%10)			parseErr("number out of range\r\n");		v = v * 10 + c;	}	return v;}static intgetc(void){	return Bgetc(&bin);}static voidungetc(void){	Bungetc(&bin);}static intpeekc(void){	int c;	c = Bgetc(&bin);	Bungetc(&bin);	return c;}

⌨️ 快捷键说明

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