📄 cxxclass.cc
字号:
CxxInfo::~CxxInfo(){ for (int i = 0; i < _classes.size(); i++) delete _classes[i];}CxxClass *CxxInfo::make_class(const String &name){ int which = _class_map[name]; if (which < 0) { CxxClass *nclass = new CxxClass(name); which = _classes.size(); _classes.push_back(nclass); _class_map.insert(name, which); } return _classes[which];}static Stringremove_crap(const String &original_text){ // Get rid of preprocessor directives, comments, string literals, and // character literals by replacing them with the right number of spaces. const char *s = original_text.data(); const char *end_s = s + original_text.length(); StringAccum new_text; char *o = new_text.extend(original_text.length()); char *if0_o_ptr = 0; while (s < end_s) { // read one line // skip spaces at beginning of line while (s < end_s && isspace(*s)) *o++ = *s++; if (s >= end_s) // end of data break; if (*s == '#') { // preprocessor directive const char *first_s = s; while (1) { while (s < end_s && *s != '\n' && *s != '\r') *o++ = ' ', s++; bool backslash = (s[-1] == '\\'); while (s < end_s && (*s == '\n' || *s == '\r')) *o++ = *s++; if (!backslash) break; } // check for '#if 0 .. #endif' const char *ss = first_s + 1; while (ss < s && isspace(*ss)) ss++; if (ss < s - 5 && ss[0] == 'e' && ss[1] == 'n' && ss[2] == 'd' && ss[3] == 'i' && ss[4] == 'f') { if (if0_o_ptr) while (if0_o_ptr < o) *if0_o_ptr++ = ' '; if0_o_ptr = 0; } else if (ss < s - 3 && ss[0] == 'i' && ss[1] == 'f') { for (ss += 2; ss < s && isspace(*ss); ss++) ; if (ss < s && ss[0] == '0') if0_o_ptr = o; } continue; } // scan; stop at EOL, comment start, or literal start while (s < end_s && *s != '\n' && *s != '\r') { // copy chars while (s < end_s && *s != '/' && *s != '\"' && *s != '\'' && *s != '\n' && *s != '\r') *o++ = *s++; if (s < end_s - 1 && *s == '/' && s[1] == '*') { // slash-star comment *o++ = ' '; *o++ = ' '; s += 2; while (s < end_s && (*s != '*' || s >= end_s - 1 || s[1] != '/')) { *o++ = (*s == '\n' || *s == '\r' ? *s : ' '); s++; } if (s < end_s) { *o++ = ' '; *o++ = ' '; s += 2; } } else if (s < end_s - 1 && *s == '/' && s[1] == '/') { // slash-slash comment *o++ = ' '; *o++ = ' '; s += 2; while (s < end_s && *s != '\n' && *s != '\r') *o++ = ' ', s++; } else if (*s == '\"' || *s == '\'') { // literal // XXX I am not sure why the closing quote, // and any characters preceded by backslash, are turned into $. char stopper = *s; *o++ = ' ', s++; while (s < end_s && *s != stopper) { *o++ = ' ', s++; if (s[-1] == '\\') *o++ = '$', s++; } if (s < end_s) *o++ = '$', s++; } else if (*s != '\n' && *s != '\r') // random other character, fine *o++ = *s++; } // copy EOL characters while (s < end_s && (*s == '\n' || *s == '\r')) *o++ = *s++; } return new_text.take_string();}static intskip_balanced_braces(const String &text, int p){ const char *s = text.data(); int len = text.length(); int brace_level = 0; while (p < len) { if (s[p] == '{') brace_level++; else if (s[p] == '}') { if (!--brace_level) return p + 1; } p++; } return p;}static intskip_balanced_parens(const String &text, int p){ const char *s = text.data(); int len = text.length(); int brace_level = 0; while (p < len) { if (s[p] == '(') brace_level++; else if (s[p] == ')') { if (!--brace_level) return p + 1; } p++; } return p;}intCxxInfo::parse_function_definition(const String &text, int fn_start_p, int paren_p, const String &original, CxxClass *cxx_class){ // find where we think open brace should be int p = skip_balanced_parens(text, paren_p); const char *s = text.data(); int len = text.length(); while (p < len && isspace(s[p])) p++; if (p < len - 5 && strncmp(s+p, "const", 5) == 0) { for (p += 5; p < len && isspace(s[p]); p++) /* nada */; } // if open brace is not there, a function declaration or something similar; // return if (p >= len || s[p] != '{') return p; // save boundaries of function body int open_brace_p = p; int close_brace_p = skip_balanced_braces(text, open_brace_p); // find arguments; cut space from end for (p = open_brace_p - 1; p >= paren_p && isspace(s[p]); p--) /* nada */; String args = original.substring(paren_p, p + 1 - paren_p); // find function name and class name for (p = paren_p - 1; p > fn_start_p && isspace(s[p]); p--) /* nada */; int end_fn_name_p = p + 1; while (p >= fn_start_p && (isalnum(s[p]) || s[p] == '_' || s[p] == '~')) p--; String fn_name = original.substring(p + 1, end_fn_name_p - (p + 1)); String class_name; if (p >= fn_start_p + 2 && s[p] == ':' && s[p-1] == ':') { int end_class_name_p = p - 1; for (p -= 2; p >= fn_start_p && (isalnum(s[p]) || s[p] == '_' || s[p] == '~'); p--) /* nada */; if (p > fn_start_p && s[p] == ':') // nested class fns uninteresting return close_brace_p; class_name = original.substring(p + 1, end_class_name_p - (p + 1)); } // find return type; skip access control declarations, cut space from end while (1) { int access_p; if (p >= fn_start_p + 6 && strncmp(s+fn_start_p, "public", 6) == 0) access_p = fn_start_p + 6; else if (p >= fn_start_p + 7 && strncmp(s+fn_start_p, "private", 7) == 0) access_p = fn_start_p + 7; else if (p >= fn_start_p + 9 && strncmp(s+fn_start_p, "protected", 9) == 0) access_p = fn_start_p + 9; else break; while (access_p < p && isspace(s[access_p])) access_p++; if (access_p == p || s[access_p] != ':') break; for (access_p++; access_p < p && isspace(s[access_p]); access_p++) /* nada */; fn_start_p = access_p; } while (p >= fn_start_p && isspace(s[p])) p--; String ret_type = original.substring(fn_start_p, p + 1 - fn_start_p); // decide if this function/class pair is OK CxxClass *relevant_class; if (class_name) relevant_class = make_class(class_name); else relevant_class = cxx_class; // define function if (relevant_class) { int body_pos = open_brace_p + 1; int body_len = close_brace_p - 1 - body_pos; relevant_class->defun (CxxFunction(fn_name, !class_name, ret_type, args, original.substring(body_pos, body_len), text.substring(body_pos, body_len))); } // done return close_brace_p;}intCxxInfo::parse_class_definition(const String &text, int p, const String &original){ // find class name const char *s = text.data(); int len = text.length(); while (p < len && isspace(s[p])) p++; int name_start_p = p; while (p < len && (isalnum(s[p]) || s[p] == '_')) p++; String class_name = original.substring(name_start_p, p - name_start_p); CxxClass *cxxc = make_class(class_name); // parse superclasses while (p < len && s[p] != '{') { while (p < len && s[p] != '{' && !isalnum(s[p]) && s[p] != '_') p++; int p1 = p; while (p < len && (isalnum(s[p]) || s[p] == '_')) p++; if (p > p1 && (p != p1 + 6 || strncmp(s+p1, "public", 6) != 0)) { // XXX private or protected inheritance? CxxClass *parent = make_class(original.substring(p1, p - p1)); cxxc->add_parent(parent); } } // parse class body return parse_class(text, p + 1, original, cxxc);}intCxxInfo::parse_class(const String &text, int p, const String &original, CxxClass *cxx_class){ // parse clean_text const char *s = text.data(); int len = text.length(); while (1) { // find first batch while (p < len && isspace(s[p])) p++; int p1 = p; while (p < len && s[p] != ';' && s[p] != '(' && s[p] != '{' && s[p] != '}') p++; //fprintf(stderr, " %d %c\n", p, s[p]); if (p >= len) return len; else if (s[p] == ';') { // uninteresting p++; continue; } else if (s[p] == '}') { //fprintf(stderr, "!!!!!!/\n"); return p + 1; } else if (s[p] == '{') { if (p > p1 + 6 && !cxx_class && (strncmp(s+p1, "class", 5) == 0 || strncmp(s+p1, "struct", 6) == 0)) { // parse class definition p = parse_class_definition(text, p1 + 6, original); } else p = skip_balanced_braces(text, p); } else if (s[p] == '(') p = parse_function_definition(text, p1, p, original, cxx_class); }}voidCxxInfo::parse_file(const String &original_text, bool header, String *store_includes){ String clean_text = remove_crap(original_text); CxxFunction::parsing_header_file = header; parse_class(clean_text, 0, original_text, 0); // save initial comments and #defines and #includes for replication. // Also skip over 'CLICK_CXX_whatever', enum definitions, typedefs, // and 'extern "C" { }' blocks enclosing headers only. // XXX Should save up to an arbitrary comment or something if (store_includes) { const char *s = clean_text.data(); int p = 0; int len = clean_text.length(); while (1) { while (p < len && isspace(s[p])) p++; if (p < len && s[p] == ';') { // mop up stray semicolons p++; } else if (p + 7 < len && memcmp(s + p, "extern", 6) == 0 && isspace(s[p+6])) { // include 'extern ["C"] { -HEADERS- }' int p1 = p + 6; while (p1 < len && (isspace(s[p1]) || s[p1] == '$')) p1++; if (p1 >= len || s[p1] != '{') break; for (p1++; p1 < len && isspace(s[p1]); p1++) /* nada */; if (p1 >= len || s[p1] != '}') break; p = p1 + 1; } else if (p + 5 < len && memcmp(s + p, "enum", 4) == 0 && isspace(s[p+4])) { // include 'enum [IDENTIFIER] { ... }' int p1 = p + 5; while (p1 < len && isspace(s[p1])) p1++; if (p1 < len && (isalnum(s[p1]) || s[p1] == '_')) { while (p1 < len && (isalnum(s[p1]) || s[p1] == '_')) p1++; while (p1 < len && isspace(s[p1])) p1++; } if (p1 >= len || s[p1] != '{') break; for (p1++; p1 < len && s[p1] != '}'; p1++) /* nada */; if (p1 >= len) break; p = p1 + 1; } else if (p + 8 < len && memcmp(s + p, "typedef", 7) == 0 && isspace(s[p+7])) { // include typedefs for (p += 8; p < len && s[p] != ';'; p++) /* nada */; } else if (p + 9 < len && memcmp(s + p, "CLICK_CXX", 9) == 0) { // include 'CLICK_CXX' (used in <click/cxxprotect.h>) for (p += 9; p < len && (isalnum(s[p]) || s[p] == '_'); p++) /* nada */; } else break; } *store_includes = original_text.substring(0, p); }}// Vector template instantiation#include <click/vector.cc>template class Vector<CxxFunction>;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -