Ejemplo n.º 1
0
Vector<String> GetLineMap(Stream& stream)
{
	Vector<String> out;
	int emp = 0;
	if(stream.IsOpen())
		while(!stream.IsEof()) {
			String s = stream.GetLine();
			const char *p = s, *e = s.End(), *f = e;
			while(e > p && (byte)e[-1] != 9 && (byte)e[-1] < ' ')
				e--;
			if(e == p)
				emp++;
			else
			{
				while(emp-- > 0)
					out.Add(Null);
				if(e != f)
					s.Trim(int(e - p));
				out.Add(s);
				emp = 0;
			}
		}
	return out;
}
Ejemplo n.º 2
0
void PPFile::Parse(Stream& in)
{
	LTIMING("PPFile::Parse");
	for(int i = 0; i < ppmacro.GetCount(); i++)
		sAllMacros.Unlink(ppmacro[i]);
	ppmacro.Clear();
	item.Clear();
	includes.Clear();
	bool was_using = false;
	bool was_namespace = false;
	int  level = 0;
	bool incomment = false;
	Vector<int> namespace_block;
	bool next_segment = true;
	Index<int> local_segments;
	keywords.Clear();
	int linei = 0;
	Md5Stream md5;
	while(!in.IsEof()) {
		String l = in.GetLine();
		while(*l.Last() == '\\' && !in.IsEof()) {
			l.Trim(l.GetLength() - 1);
			l.Cat(in.GetLine());
		}
		RemoveComments(l, incomment);
		try {
			CParser p(l);
			if(p.Char('#')) {
				if(p.Id("define")) {
					if(next_segment) {
						PPItem& m = item.Add();
						m.type = PP_DEFINES;
						m.segment_id = ++sPPserial;
						next_segment = false;
						local_segments.Add(sPPserial);
					}
					CppMacro def;
					String   id = def.Define(p.GetPtr());
					if(id.GetCount()) {
						PPMacro m;
						m.segment_id = sPPserial;
						m.line = linei;
						m.macro = def;
						ppmacro.Add(sAllMacros.Put(id, m));
						md5.Put("#", 1);
						md5.Put(id);
						md5.Put(0);
						md5.Put(m.macro.md5, 16);
					}
				}
				else
				if(p.Id("undef")) {
					if(p.IsId()) {
						String id = p.ReadId();
						md5.Put("#", 1);
						md5.Put(id);
						md5.Put(1);
						int segmenti = -1;
						PPMacro *um = FindPPMacro(id, local_segments, segmenti);
						if(um && segmenti) { // heuristic: only local undefs are allowed
							PPItem& m = item.Add();
							m.type = PP_DEFINES;
							m.segment_id = ++sPPserial;
							um->undef_segment_id = m.segment_id;
							next_segment = true;
							local_segments.Add(sPPserial);
							if(id.GetCount()) {
								PPMacro m;
								m.segment_id = sPPserial;
								m.line = linei;
								m.macro.SetUndef();
								ppmacro.Add(sAllMacros.Put(id, m));
							}
						}
					}
				}
				else
				if(p.Id("include")) {
					PPItem& m = item.Add();
					next_segment = true;
					m.type = PP_INCLUDE;
					m.text = TrimBoth(p.GetPtr());
					if(IsNull(m.text))
						item.Drop();
					else
						includes.FindAdd(m.text);
					md5.Put('@');
					md5.Put(m.text);
				}
			}
			else {
				while(!p.IsEof()) {
					if(was_namespace) {
						int type = was_using ? PP_USING : PP_NAMESPACE;
						String id;
						while(p.Char2(':', ':'))
							id = "::";
						if(p.IsId()) {
							id << p.ReadId();
							while(p.Char2(':', ':') && p.IsId())
								id << "::" << p.ReadId();
							if(!was_using)
								namespace_block.Add(level);
							if(!was_using || level == 0) {
								PPItem& m = item.Add();
								next_segment = true;
								m.type = type;
								m.text = id;
							}
							md5.Put('$');
							md5.Put(type);
							md5.Put(id);
						}
						was_namespace = was_using = false;
					}
					else
					if(p.Id("using"))
						was_using = true;
					else
					if(p.Id("namespace"))
						was_namespace = true;
					else {
						was_using = was_namespace = false;
						if(p.IsId()) {
							static const VectorMap<String, String>& namespace_macro = GetNamespaceMacros();
							static const Index<String>& namespace_end_macro = GetNamespaceEndMacros();

							String id = p.ReadId();
							int q = namespace_macro.Find(id);
							if(q > 0) {
								PPItem& m = item.Add();
								next_segment = true;
								m.type = PP_NAMESPACE;
								m.text = namespace_macro[q];
								namespace_block.Add(level);
								level++;
								md5.Put('%');
								md5.Put(id);
							}
							else {
								q = namespace_end_macro.Find(id);
								if(q >= 0) {
									level--;
									CheckEndNamespace(namespace_block, level, md5);
								}
							}
							keywords.Add(id);
						}
						else
						if(p.Char('}')) {
							if(level > 0) {
								level--;
								CheckEndNamespace(namespace_block, level, md5);
							}
						}
						else
						if(p.Char('{'))
							level++;
						else
							p.SkipTerm();
					}
				}
			}
		}
		catch(...) {}
		linei++;
	}
	md5sum = md5.FinishString();
	Sort(keywords);
	Vector<int> remove;
	int i = 0;
	while(i < keywords.GetCount()) { // Remove identical items
		int ii = i;
		i++;
		while(i < keywords.GetCount() && keywords[ii] == keywords[i])
			remove.Add(i++);
	}
	keywords.Remove(remove);
}
Ejemplo n.º 3
0
SrcFile PreProcess(Stream& in, Parser& parser) // This is not really C preprocess, only removes (or processes) comment and directives
{
	SrcFile res;
	bool include = true;
	int lineno = 0;
	while(!in.IsEof()) {
		String ln = in.GetLine();
		lineno++;
		SLPos(res);
		while(*ln.Last() == '\\') {
			ln.Trim(ln.GetLength() - 1);
			ln.Cat(in.GetLine());
			SLPos(res);
		}
		const char *rm = ln;
		if(IsAlNum(*rm)) {
			const char *s = ln;
			bool islbl = false;
			bool wassemi = false;
			while(*s && iscid(*s) || findarg(*s, '\t', ' ', ':') >= 0) { // check for label, labeled lines are not grounded
				if(*s == ':' && !wassemi) {
					islbl = true;
					wassemi = true; // second ':' cancels label
				}
				else
				if(*s != '\t' && *s != ' ')
					islbl = false; // something was after the label, e.g. void Foo::Bar()
				s++;
			}
			if(!islbl)
				res.text << '\2';
		}
		else
		if(*rm == '\x1f') // line started with macro
			res.text << '\2';
		while(*rm == ' ' || *rm == '\t') rm++;
		if(*rm == '\0')
			res.blankLinesRemoved++;
		else
		if(*rm == '#')
		{
			const char *s = rm + 1;
			while(*s == ' ' || *s == '\t')
				s++;
			if(s[0] == 'd' && s[1] == 'e' && s[2] == 'f' &&
			   s[3] == 'i' && s[4] == 'n' && s[5] == 'e' && !iscid(s[6])) {
				s += 6;
				while(*s == ' ' || *s == '\t') s++;
				String macro;
				while(iscid(*s))
					macro.Cat(*s++);
				if(*s == '(') {
					while(*s != ')' && *s)
						macro.Cat(*s++);
					macro << ')';
				}
				if(include)
					parser.AddMacro(lineno, macro);
			}
			res.preprocessorLinesRemoved++;
		}
		else {
			bool lineContainsComment = false;
			bool lineContainsNonComment = false;
			String cmd;
			while(*rm) {
				if(*rm == '\"') {
					lineContainsNonComment = true;
					res.text << '\"';
					rm++;
					while((byte)*rm && *rm != '\r' && *rm != '\n') {
						if(*rm == '\"') {
							res.text << '\"';
							rm++;
							break;
						}
						if(*rm == '\\' && rm[1]) {
							if(include)
								res.text.Cat(*rm);
							rm++;
						}
						if(include)
							res.text.Cat(*rm);
						rm++;
					}
				}
				else
				if(*rm == '\\' && rm[1]) {
					lineContainsNonComment = true;
					if(include) {
						res.text.Cat(*rm++);
						res.text.Cat(*rm++);
					}
					else
						rm += 2;
				}
				else
				if(rm[0] == '/' && rm[1] == '/') {
					cmd = rm + 2;
					if(!lineContainsNonComment)
						res.commentLinesRemoved++;
					break;
				}
				else
				if(rm[0] == '/' && rm[1] == '*') {
					lineContainsComment = true;
					rm += 2;
					for(;;) {
						if(*rm == '\0') {
							if(!lineContainsNonComment)
								res.commentLinesRemoved++;
							if(in.IsEof()) break;
							SLPos(res);
							ln = in.GetLine();
							rm = ~ln;
							lineContainsNonComment = false;
						}
						if(rm[0] == '*' && rm[1] == '/') {
							rm += 2;
							break;
						}
						rm++;
					}
					if(include)
						res.text.Cat(' ');
				}
				else {
					lineContainsNonComment = true;
					if(include)
						res.text.Cat(*rm);
					rm++;
				}
			}
			if(include)
				res.text << ' ';
			if(cmd[0] == '$') {
				if(cmd[1] == '-') include = false;
				if(cmd[1] == '+') include = true;
				if(cmd[1]) {
					res.text.Cat(~cmd + 2);
					res.text.Cat(' ');
				}
			}
			if(lineContainsComment && !lineContainsNonComment)
				res.commentLinesRemoved++;
		}
	}
	return pick(res);
}
Ejemplo n.º 4
0
// Загружает INI-структуру из потока. При возникновении ошибки возвращает false
// s - поток для загрузки
bool IniFile::Load(Stream& s, int charset)
{
    Content.Clear();

    int sIndex = -1;
    int nIndex = -1;

    String buffer;
    bool complete;
    bool skip;
    int last;
    int flags = 0;
    String line;

    while(!s.IsEof())
    {
        line = ::ToCharset(CHARSET_DEFAULT, s.GetLine(), charset);
        line << '\n';

        for (int i = 0; i < line.GetCount(); ++i)
        {
            int c = line[i];

            bool lastSplash = __slash;
            last = flags % 1000;
            Rule(flags, c, skip, complete);

            if (!__slash)
                if (!skip)
                    if (c != '\n' && c != '\r' && c != '\"') buffer << (char)c;

            if (lastSplash && __slash)
            {
                if (c == '\"') {
                    buffer << '\"';
                    __slash = false;
                }
                else if (c == '[') {
                    buffer << '[';
                    __slash = false;
                }
                else if (c == ']') {
                    buffer << ']';
                    __slash = false;
                }
                else if (c == '=') {
                    buffer << '=';
                    __slash = false;
                }
                else if (c == ',') {
                    buffer << ',';
                    __slash = false;
                }
                else {
                    buffer << '\\';
                    __slash = false;
                }
            }

            if (complete && !buffer.IsEmpty())
            {
                if (last == 100)
                {
                    sIndex++;
                    nIndex = -1;
                    Content.Add(IniConvert(buffer, false));
                }

                if (last == 10)
                {
                    nIndex++;
                    Content[sIndex].Content.Add(IniConvert(buffer, false));
                }

                if (last == 1)
                    Content[sIndex].Content[nIndex].Content.Add(IniConvert(buffer, false));

                buffer.Clear();
            }
        }
    }

    return true;
}
Ejemplo n.º 5
0
static void LoadIniStream(Stream& in, VectorMap<String, String>& key, const char *sfile)
{
	bool env = false;
	while(!in.IsEof()) {
		String line = in.GetLine();
		CParser p(line);
		if(p.IsId()) {
			String k = p.ReadId();
			if(p.Char('=')) {
				String h = TrimBoth((String)p.GetSpacePtr());
				if(env) {
					String hh;
					const char *s = ~h;
					while(*s) {
						if(*s == '$') {
							s++;
							if(*s == '$') {
								hh.Cat('$');
								s++;
							}
							else {
								String id;
								if (*s == '{') {
									while(*++s != '}')
										id.Cat(*s);
									s++;
								} else {
									while(iscid(*s))
										id.Cat(*s++);
								}
								hh.Cat(GetEnv(id));
							}
						}
						else
							hh.Cat(*s++);
					}
					key.Add(k, hh);
				}
				else
					key.Add(k, h);
			}
		}
		else
		if(p.Char('@')) {
			if(p.Id("include")) {
				String fn = p.GetPtr();
				if(!IsFullPath(fn) && sfile)
					fn = AppendFileName(GetFileFolder(GetFullPath(sfile)), fn);
				LoadIniFile(fn, key);
			}
			else
			if(p.Id("end"))
				return;
			else
			if(p.Id("replace-env"))
				env = true;
			else
			if(p.Id("ignore-env"))
				env = false;
		}
	}
}