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; }
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); }
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); }
// Загружает 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; }
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; } } }