#ifndef IDA_HIGHLIGHTER #define IDA_HIGHLIGHTER #include idaman void ida_export code_highlight_block(void *context, highlighter_cbs_t *highlighter_cbs, const qstring &text); // returns the length of text to colorize // negative values may have special meaning in the future. typedef ssize_t idaapi external_colorizer_t(syntax_highlight_style *color, const char *str); typedef qvector external_colorizers_t; // returns true if identifier is colorized typedef bool idaapi external_ident_colorizer_t(syntax_highlight_style *color, const qstring &ident); typedef qvector external_ident_colorizers_t; #define MLTCMTMASK 0xF #define PREPROC_FLAG 0x10 // Common implementation of syntax_highlighter_t used in different parts of IDA //-V:ida_syntax_highlighter_t:730 not all members of a class are initialized inside the constructor struct ida_syntax_highlighter_t : syntax_highlighter_t { protected: // keys of keywords_t point to memory from keyword_strings. // once allocated, this buffer won't be moved in the memory. qstrvec_t keyword_memory; // helper class so that keywords_t gets sorted by string contents, not pointer values. struct plain_char_ptr_t { const char *ptr; plain_char_ptr_t(const char *p = NULL) : ptr(p) {} bool operator <(const plain_char_ptr_t &r) const { return strcmp(ptr, r.ptr) < 0; } bool operator ==(const plain_char_ptr_t &r) const { return strcmp(ptr, r.ptr) == 0; } }; struct multicmt_t { qstring open_multicmt; qstring close_multicmt; multicmt_t() {} multicmt_t(const char *_open_multicmt, const char *_close_multicmt) : open_multicmt(_open_multicmt), close_multicmt(_close_multicmt) {} }; // typedef std::map keywords_t; struct keywords_style_t { qvector keywords; syntax_highlight_style style; }; typedef qvector keywords_t; //typedef qvector keywords_t; typedef qvector multicmtvec_t; keywords_t keywords; qstring open_cmt; // string that opens a regular line comment multicmtvec_t multicmts; char literal_closer; // either close_strconst or close_chrconst for the current literal // color mappings syntax_highlight_style text_color = HF_DEFAULT; syntax_highlight_style comment_color = HF_COMMENT; syntax_highlight_style string_color = HF_STRING; syntax_highlight_style preprocessor_color = HF_PREPROC; external_colorizers_t external_colorizers; external_ident_colorizers_t external_ident_colorizers; // work variables const char *input; // pointer to the start of the input buffer const char *pending; // pointer in the input buffer syntax_highlight_style style = HF_DEFAULT; // current highlighting style bool pending_nonspaces_present(const char *end) { for ( const char *p = pending; p != end; ++p ) if ( !qisspace(*p) ) return true; return false; } const char *parse_literal_const(highlighter_cbs_t *highlighter_cbs, const char *ptr, char literal_closer); void flush_output(highlighter_cbs_t *highlighter_cbs, const char *ptr, syntax_highlight_style style); void handle_cmt(highlighter_cbs_t *highlighter_cbs, int mcmt_idx, const char **ptr); void handle_preproc(highlighter_cbs_t *highlighter_cbs, const char **ptr); public: // if any of the following features is not needed, just zero them out: char open_strconst; // character that opens a string constant char close_strconst; // character that closes a string constant char open_chrconst; // character that closes a character constant char close_chrconst; // character that opens a character constant char escape_char; // backslash char preprocessor_char; // # ida_syntax_highlighter_t() : syntax_highlighter_t(&code_highlight_block) {} void highlight_block_ex(highlighter_cbs_t *highlighter_cbs, const qstring &text); void add_external_colorizer(external_colorizer_t *th) { external_colorizers.push_back(th); } void add_external_ident_colorizer(external_ident_colorizer_t *th) { external_ident_colorizers.push_back(th); } void set_open_cmt(const char *begin) { open_cmt = begin; } void add_multi_line_comment(const char *begin, const char *end) { multicmt_t &mcmt = multicmts.push_back(); mcmt.open_multicmt = begin; mcmt.close_multicmt = end; } void add_keywords(const char *kwstr, syntax_highlight_style _style) { char *ctx; // in order not to allocate every keyword separately, we allocate the whole // kwstr string at once and will just store pointers to it in the map. qstring &mem = keyword_memory.push_back(); mem = kwstr; keywords_style_t *pair_p = NULL; for ( int i = 0; i < keywords.size(); i++ ) { if ( keywords[i].style == _style ) { pair_p = &keywords[i]; break; } } if ( pair_p == NULL ) { keywords_style_t &pair = keywords.push_back(); pair_p = &pair; pair_p->style = _style; } for ( char *kw = qstrtok(mem.begin(), "|", &ctx); kw != NULL; kw = qstrtok(NULL, "|", &ctx) ) pair_p->keywords.push_back(kw); } }; #endif // IDA_HIGHLIGHTER