String DocDir::GetAddFileName(const String& package, const DocKey& key, int type) { Entry& w = dir.GetAdd(package).GetAdd(key); String& fn = w.text; w.type = type; if(!IsEmpty(fn)) return fn; String nm = key.nameing + '_' + key.nesting + '_' + key.item; String n; const char *s = nm; while(*s && n.GetLength() < 30) if(iscid(*s)) n.Cat(*s++); else { n.Cat('_'); while(*s && !iscid(*s)) s++; } n << '_' << LNGAsText(key.lang); int i = 0; for(;;) { fn = n + FormatIntAlpha(i) + ".dpp"; if(!FindFile(DocFile(package, fn))) return fn; i++; } }
bool Ide::SearchInFile(const String& fn, const String& pattern, bool wholeword, bool ignorecase, int& n, RegExp *regexp) { FileIn in(fn); if(!in) return true; int ln = 1; bool wb = wholeword ? iscid(*pattern) : false; bool we = wholeword ? iscid(*pattern.Last()) : false; int infile = 0; while(!in.IsEof()) { String line = in.GetLine(); bool bw = true; int count; if(regexp) { if(regexp->Match(line)) AddFoundFile(fn, ln, line, regexp->GetOffset(), regexp->GetLength()); } else for(const char *s = line; *s; s++) { if(bw && Match(pattern, s, we, ignorecase, count)) { AddFoundFile(fn, ln, line, int(s - line), count); infile++; n++; break; } if(wb) bw = !iscid(*s); } ln++; } in.Close(); int ffs = ~ff.style; if(infile && ffs != STYLE_NO_REPLACE) { EditFile(fn); bool doit = true; if(ffs == STYLE_CONFIRM_REPLACE) { editor.SetCursor(0); editor.Find(false, true); switch(PromptYesNoCancel(NFormat("Replace %d lines in [* \1%s\1]?", infile, fn))) { case 1: break; case 0: doit = false; break; case -1: return false; } } if(doit) { editor.SelectAll(); editor.BlockReplace(); SaveFile(); ffound.Add(fn, Null, AsString(infile) + " replacements made"); ffound.Sync(); } } return true; }
String QualifyIds(ScopeInfo& nf, const String& k, const String& usings, bool all) { LTIMING("QualifyIds"); String r; const char *s = k; Vector<String> empty; while(*s) { int c = *s; if(c == ':') { const char *b = s++; while(*s == ':' || iscid(*s)) s++; /* if(all) { if(iscid(*r.Last())) r << ' '; ScopeInfo nnf(nf.GetScope(), nf.base); Qualify(r, nnf, b, s, usings); } else*/ r.Cat(b, s); } else if(iscid(c)) { if(iscid(*r.Last())) r << ' '; if(s[0] == 'c' && s[1] == 'o' && s[2] == 'n' && s[3] == 's' && s[4] == 't' && !iscid(s[5])) { r << s_const; s += 5; } else if(s[0] == 'm' && s[1] == 'u' && s[2] == 't' && s[3] == 'a' && s[4] == 'b' && s[5] == 'l' && s[6] == 'e' && !iscid(s[7])) { r << "mutable"; s += 7; } else if(s[0] == 'v' && s[1] == 'o' && s[2] == 'l' && s[3] == 'a' && s[4] == 't' && s[5] == 'i' && s[6] == 'l' && s[7] == 'e' && !iscid(s[8])) { r << "volatile"; s += 8; } else { const char *b = s++; while(*s == ':' || iscid(*s)) s++; if(all) Qualify(r, nf, b, s, usings); else r.Cat(b, s); } } else { if(c == '(') all = true; if(c != ' ') r.Cat(c); s++; } } return r; }
static String MakeIdent(const char *name) { String out; for(; *name; name++) out << (iscid(*name) ? *name : '_'); return out; }
bool Match(const char *f, const char *s, bool we, bool ignorecase, int& count) { const char *b = s; while(*f) { if(*f == WILDANY) { f++; for(;;) { if(Match(f, s, we, ignorecase, count)) { count += int(s - b); return true; } if(!*s++) break; } return false; } else if(*f == WILDONE) { if(!*s++) return false; } else if(*f == WILDSPACE) { if(*s != ' ' && *s != '\t') return false; s++; while(*s == ' ' || *s == '\t') s++; } else if(*f == WILDNUMBER) { if(*s < '0' || *s > '9') return false; s++; while(*s >= '0' && *s <= '9') s++; } else if(*f == WILDID) { if(!iscib(*s)) return false; s++; while(iscid(*s)) s++; } else { if(ignorecase ? ToUpper(*s) != ToUpper(*f) : *s != *f) return false; s++; } f++; } count = int(s - b); return we && iscid(*s) ? false : true; }
void Lex::Next() { grounding = false; while((byte)*ptr <= ' ') { if(*ptr == '\2') grounding = true; if(*ptr == '\0') return; ptr++; } pos = ptr; int c = (byte)*ptr++; if(c == '\0') return; switch(c) { case_id: { String x; x.Reserve(12); x.Cat(c); while(iscid(*ptr)) x.Cat(*ptr++); int q = id.FindAdd(x); if(q == tk_rval_ - 256) { // simple hack for transitionary macro AddCode('&'); AddCode('&'); } else AddCode(q + 256); break; } case ':': AddCode(Char(':') ? t_dblcolon : ':'); break; case '*': AssOp('*', t_mulass); break; case '/': AssOp('/', t_divass); break; case '%': AssOp('%', t_modass); break; case '^': AssOp('^', t_xorass); break; case '!': AssOp('!', t_neq); break; case '.': if(Char('*')) AddCode(t_dot_asteriks); else if(*ptr == '.' && ptr[1] == '.') { AddCode(t_elipsis); ptr += 2; } else AddCode('.'); break; case '+': if(Char('+')) AddCode(t_inc); else AssOp('+', t_addass); return; case '-': if(Char('-')) AddCode(t_dec); else if(Char('>')) AddCode(Char('*') ? t_arrow_asteriks : t_arrow); else AssOp('-', t_subass); break; case '&': if(Char('&')) AddCode(t_and); else AssOp('&', t_andass); break; case '|': if(Char('|')) AddCode(t_or); else AssOp('|', t_orass); break; case '=': AssOp('=', t_eq); break; case '<': if(Char('<')) AssOp(t_shl, t_shlass); else AssOp('<', t_le); break; case '>': if(Char('>')) AssOp(t_shr, t_shrass); else AssOp('>', t_ge); break; case '0': { dword w = 0; if(Char('x') || Char('X')) { for(;;) { int d; if(*ptr >= '0' && *ptr <= '9') d = *ptr - '0'; else if(*ptr >= 'A' && *ptr <= 'F') d = *ptr - 'A' + 10; else if(*ptr >= 'a' && *ptr <= 'f') d = *ptr - 'a' + 10; else break; if(w >= 0x8000000u - d) { AddCode(te_integeroverflow); return; } w = w * 16 + d - '0'; ptr++; } } else while(*ptr >= '0' && *ptr <= '7') { int d = *ptr++ - '0'; if(w >= 0x1000000u - d) { AddCode(te_integeroverflow); return; } w = w * 8 + d - '0'; } Term& tm = term.AddTail(); tm.code = t_integer; tm.ptr = pos; tm.number = w; } break; case_nonzero_digit: { double w = c - '0'; bool fp = false; while(*ptr >= '0' && *ptr <= '9') w = w * 10 + *ptr++ - '0'; if(*ptr == '.') { //TODO TO BE Completed !!! fp = true; ptr++; double x = 0.1; while(*ptr >= '0' && *ptr <= '9') { w += x * (*ptr++ - '0'); x /= 10; } } Term& tm = term.AddTail(); if(fp || w < INT_MIN || w > INT_MAX) tm.code = t_double; else tm.code = t_integer; tm.ptr = pos; tm.number = w; } break; case '\'': { Term& tm = term.AddTail(); tm.code = t_character; tm.ptr = pos; tm.text = String(GetCharacter(), 1); if(*ptr == '\'') ptr++; else tm.code = te_badcharacter; } break; case '\"': { Term& tm = term.AddTail(); tm.code = t_string; tm.ptr = pos; for(;;) { while(*ptr != '\"') { if((byte)*ptr < ' ' && *ptr != 9) { tm.code = te_badstring; return; } tm.text.Cat(GetCharacter()); } ptr++; while(*ptr && (byte)*ptr <= ' ') ptr++; if(*ptr != '\"') break; ptr++; } } break; default: AddCode(c); return; } }
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); }
void Parser::Do() { while(lex != t_eof && lex != '}') { Line(); if(Key(tk_using)) { while(!Key(';')) ++lex; } else if(Key(tk_extern) && lex == t_string) { ++lex; ++lex; if(Key('{')) { Do(); Key('}'); } Key(';'); } else if(Key(tk_template)) { if(lex.IsId() || lex == tk_class && lex.IsId(1)) { Key(tk_class); for(;;) { if(lex.IsId()) lex.GetId(); else if(!Key(t_dblcolon)) break; } TemplateParams(); Key(';'); } else { String tnames; String tparam = TemplateParams(tnames); if(!Nest(tparam, tnames)) { Array<Decl> r = Declaration(true, true); for(int i = 0; i < r.GetCount(); i++) { Decl& d = r[i]; d.natural = "template" + tparam + ' ' + d.natural; if(context.access != PRIVATE && !d.isfriend && d.function) { CppItem& im = Item(context.nameing, context.nesting, d.natural); im.name = d.name; im.access = context.access; im.header = Purify(d.header); im.ender = Purify(d.ender); im.kind = context.nesting.IsEmpty() ? FUNCTIONTEMPLATE : d.s_static ? CLASSFUNCTIONTEMPLATE : INSTANCEFUNCTIONTEMPLATE; for(int i = 0; i < d.param.GetCount(); i++) { ScAdd(im.param, d.param[i].natural); ScAdd(im.pname, d.param[i].name); } im.tname = tnames; im.tparam = CleanTp(tparam); } } EatBody(); Key(';'); } } } else if(lex == tk_enum && (lex[1] == '{' || lex[2] == '{')) { ++lex; String name; if(lex.IsId()) name = lex.GetId(); String param; String pname; String n = "enum " + name + " { "; Key('{'); for(;;) { String val; Check(lex.IsId(), "Expected identifier"); String nm = lex.GetId(); if(Key('=')) val = Constant(); if(!param.IsEmpty()) n << ", "; n << nm; ScAdd(param, nm + " = " + val); ScAdd(pname, nm); Key(','); if(Key('}')) break; } n << " }"; CppItem& im = Item(context.nameing, context.nesting, n); im.kind = ENUM; im.name = name; im.access = context.access; im.param = param; im.pname = pname; if(lex.IsId()) im.name = lex.GetId(); CheckKey(';'); } else if(Key('#')) { String n = lex.GetText(); CppItem& im = Item(context.nameing, context.nesting, n); im.kind = MACRO; im.name.Clear(); const char *s = n; while(*s && iscid(*s)) im.name.Cat(*s++); s = strchr(n, '('); if(s) { s++; String p; for(;;) { if(iscid(*s)) p.Cat(*s++); else { ScAdd(im.pname, p); p.Clear(); if(*s == ')' || *s == '\0') break; s++; } } } im.access = context.access; } else if(!Nest(String(), String())) { if(Key(tk_public)) { context.access = PUBLIC; Key(':'); } else if(Key(tk_private)) { context.access = PRIVATE; Key(':'); } else if(Key(tk_protected)) { context.access = PROTECTED; Key(':'); } else { const char *p = lex.Pos(); Array<Decl> r = Declaration(true, true); bool body = EatBody(); for(int i = 0; i < r.GetCount(); i++) { Decl& d = r[i]; if(context.access != PRIVATE && !d.isfriend || d.isfriend && body) { CppItem& im = Item(context.nameing, context.nesting, d.natural); im.name = d.name; im.header = Purify(d.header); im.ender = Purify(d.ender); im.access = context.access; if(d.function) { im.kind = d.istructor ? (d.isdestructor ? DESTRUCTOR : CONSTRUCTOR) : d.isfriend ? INLINEFRIEND : context.nesting.IsEmpty() ? FUNCTION : d.s_static ? CLASSFUNCTION : INSTANCEFUNCTION; for(int i = 0; i < d.param.GetCount(); i++) { ScAdd(im.param, d.param[i].natural); ScAdd(im.pname, d.param[i].name); } } else im.kind = d.type_def ? TYPEDEF : context.nesting.IsEmpty() ? VARIABLE : d.s_static ? CLASSVARIABLE : INSTANCEVARIABLE; } } EatBody(); Key(';'); } } } }
bool MatchCib(const String& s, const String& match) { if(IsNull(match)) return true; int q = ToUpper(s).Find(match); return q > 0 && !iscid(s[q - 1]) || q == 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; } } }