📄 syntax.c
字号:
if (g_status.copied && line == g_status.buff_node) { ll = g_status.line_buff; len = g_status.line_buff_len; } else { ll = line->line; len = line->len; } old_type = line->prev->type; in_prepro = (old_type & PREPRO) && !(old_type & PREPRO_END); in_comment = ((old_type & (COM_START | COM_WHOLE)) != 0); in_string = ((old_type & (STR_START | STR_WHOLE)) != 0); in_character = ((old_type & (CHR_START | CHR_WHOLE)) != 0); type = line->type & DIRTY; /* keep the dirty flag, clear the rest */ /* * If this line continues the preprocessor then indicate as such. */ if (in_prepro) type |= PREPRO; i = 0; /* * Skip leading blanks and test for preprocessor. */ if (!in_prepro && !in_comment && !in_string && !in_character) { for (; i < len && bj_isspace( ll[i] ); ++i) ; this = (i < len) ? ll[i] : '\0'; next = (i+1 < len) ? ll[i+1] : '\0'; if ( syntax->prepro[0] && this == syntax->prepro[0] && (!syntax->prepro[1] || next == syntax->prepro[1])) { type |= PREPRO | PREPRO_START; in_prepro = TRUE; ++i; if (syntax->prepro[1]) ++i; } } com_bit = old_type & COM_NUMBER; com_num = (com_bit != 0); for (; i < len; ++i) { while (bj_isspace( ll[i] ) && ++i < len); if (i == len) break; this = ll[i]; next = (i+1 < len) ? ll[i+1] : '\0'; /* * Search for the end of the comment. */ if (in_comment) { com_len = match_comment( syntax->comend[com_num], ll, i, len ); if (com_len) { if (type & COM_START) type &= ~(COM_START | COM_NUMBER); else type |= COM_END | com_bit; in_comment = FALSE; i += com_len - 1; } continue; } /* * Search for the end of the string. */ if (in_string) { if (syntax->escape && this == syntax->escape) ++i; else if (this == syntax->strend) { if (type & STR_START) type &= ~STR_START; else { type |= STR_END; if (old_type & (START_VALID | WHOLE_VALID)) type |= END_VALID; } in_string = FALSE; } continue; } /* * Search for the end of a character literal/string. */ if (in_character) { if (syntax->escape && this == syntax->escape) ++i; else if (this == syntax->charend) { if (type & CHR_START) type &= ~CHR_START; else { type |= CHR_END; if (old_type & (START_VALID | WHOLE_VALID)) type |= END_VALID; } in_character = FALSE; } continue; } /* * If it's a line comment, the rest of the line can be ignored. */ if (syntax->comment[0][0]) { if (match_comment( syntax->comment[0], ll, i, len )) break; if (syntax->comment[1][0]) { if (match_comment( syntax->comment[1], ll, i, len )) break; } } /* * Start of a multi-line comment? */ if (syntax->comstart[0][0]) { com_num = 0; com_bit = 0; com_len = match_comment( syntax->comstart[0], ll, i, len ); if (!com_len && syntax->comstart[1][0]) { com_num = 1; com_bit = COM_NUMBER; com_len = match_comment( syntax->comstart[1], ll, i, len ); } if (com_len) { type |= COM_START | com_bit; in_comment = TRUE; i += com_len - 1; continue; } } /* * Start of a string? */ if (syntax->strstart && this == syntax->strstart) { type |= STR_START; in_string = TRUE; continue; } /* * Start of a character literal/string? */ if (syntax->charstart && this == syntax->charstart) { type |= CHR_START; in_character = TRUE; if (syntax->charnum) { ++i; if (syntax->escape && next == syntax->escape) ++i; } continue; } /* * Skip all characters in identifiers and numbers. This is primarily so * PERL's package naming will be correctly handled (eg. main'dumpvar is * one word, not a word and the start of a string). */ if (syntax->identifier[this] & (ID_STARTWORD | ID_DIGIT)) { while (++i < len && (syntax->identifier[ll[i]] & (ID_INWORD | ID_DIGIT))); --i; } } /* * If we finish in a comment/string/character, and it didn't start on this * line, then it must occupy the whole line. */ if (in_comment) { if (!(type & COM_START)) type |= COM_WHOLE | com_bit; } else if (in_string) { if (!(type & STR_START)) type |= STR_WHOLE; } else if (in_character) { if (!(type & CHR_START)) type |= CHR_WHOLE; } /* * Determine the validity of a spanning string/character. */ this = (len) ? ll[len-1] : '\0'; if ((in_string && (syntax->strnewl || (syntax->strspan && this == syntax->strspan))) || (in_character && (syntax->charnewl || (syntax->charspan && this == syntax->charspan)))) { if (type & (STR_START | CHR_START)) type |= START_VALID; else if (old_type & (START_VALID | WHOLE_VALID)) type |= WHOLE_VALID; } /* * Does the preprocessor stop here? */ if (in_prepro && !in_string && !in_character) if (in_comment || !syntax->prepspan || this != syntax->prepspan) type |= PREPRO_END; line->type = type;}/* * Name: syntax_check_lines * Purpose: update a line's syntax flags and see if the change propagates * Passed: line: first line to check * syntax: info to check against * Returns: the number of lines after this one that were changed. * Notes: propagation occurs when something affects following lines, such as * adding an opening multi-line comment. * jmh 980728: Changed return type to long from int. * jmh 980729: Test for eof. */long syntax_check_lines( line_list_ptr line, LANGUAGE *syntax ){syntax_info *info;long old_type, new_type;long count = -1; /* Don't count the first line */ if (syntax == NULL || line == NULL || line->len == EOF) return 0; info = syntax->info; do { old_type = line->type | DIRTY; /* DIRTY is or'ed for the comparison */ syntax_check( line, info ); new_type = line->type | DIRTY; ++count; line = line->next; } while (new_type != old_type && line->len != EOF); return( count );}/* * Name: syntax_check_block * Purpose: check a number of lines * Author: Jason Hood * Date: July 29, 1998 * Passed: br: number of first line to check * er: number of last line * line: pointer to first line * syntax: info to check against * Returns: none. * Notes: Checks lines modified by block functions. * br and er need not be actual line numbers, just a line range. * * jmh 031027: test for EOF. */void syntax_check_block( long br, long er, line_list_ptr line, LANGUAGE *syntax ){syntax_info *info; if (syntax != NULL) { info = syntax->info; for (; br <= er && line->len != EOF; ++br) { syntax_check( line, info ); line = line->next; } if (line->len != EOF) syntax_check_lines( line, syntax ); }}/* * Name: syntax_attr * Purpose: determine the attributes (ie. colors) of a line * Passed: line: the line under consideration * attr: buffer to hold the attributes * syntax: syntax highlighting info * Returns: attribute to use for the trailing blanks * Notes: used by update_line(). * attr should be at least as long as the line. * The line should be detabbed. * I've assumed that characters that can span lines don't have a * length limit. Characters that have a limit must have at least one * character. ie. the empty character string is not allowed (eg. ''). * This allows Ada's apostrophe "'''" to work correctly. * In rare circumstances, strings and characters that use escapes and * span lines will fail. Eg. with C, \ is used to quote the next * character and to continue the string on the next line. A string * that ends like "string end \\" (where the terminating quote is * actually eol) can be treated in two ways: a quoted \, which causes * an unterminated string (BC3.1 does this, which is what I would * expect); or as a continuing string, where the character to be * quoted starts on the next line (this is what gcc 2.7.2.1 does). * For simplicity, I do the latter. (Actually, gcc allows all lines * to have continuing backslashes - including line comments.) * The character limit could fail with the \nnn & \xnn escapes. * Eg. if the limit is 2 (C, with 16-bit ints) then the legitimate * character literal '\377' will register as 3 characters. (The * supplied C and C++ limits are set to 4.) * Everything in a preprocessor is in that color, except comments and * bad items (currently strings, characters and numbers). * attr should really be int (to be consistent), but char is a lot * easier (in update_line()), and allows memset() to be used. * * Note that _START can't be used to memset everything from here to * the end, since there's no guarantee that this is the one to which * the _START applies. eg: * * "string" "multi-line * * If STR_START is used to memset and return, then it would do so at * the `"string"' part, not the `"multi-line' part. * Ask me how I know this. :) */int syntax_attr( text_ptr text, int len, long type, unsigned char *attr, LANGUAGE *syntax ){syntax_info *info;int i;int col = syntax_color[COL_NORMAL];int in_comment;int in_string;int in_character;int in_prepro;int start = -1; /* position where something started */int count = 0; /* number of characters in that something */int char_count; /* are we counting characters? */char word[1042]; /* Store a possible keyword */text_ptr keyword;int base; /* base for numbers */unsigned char this, next;int com_len, com_num = 0;long com_bit; info = syntax->info; sort.order_array = (info->icase == MATCH) ? sort_order.match : sort_order.ignore; in_prepro = (type & PREPRO) && !(type & PREPRO_START); in_comment = ((type & (COM_WHOLE | COM_END)) != 0); in_string = ((type & (STR_WHOLE | STR_END)) != 0); in_character = ((type & (CHR_WHOLE | CHR_END)) != 0); if (in_prepro) col = syntax_color[COL_PREPRO]; if (in_comment) { col = syntax_color[COL_COMMENT]; com_bit = type & COM_NUMBER; com_num = (com_bit != 0); } else if (in_string || in_character) { if (type & (WHOLE_VALID | END_VALID)) { if (!in_prepro) col = syntax_color[in_string ? COL_STRING : COL_CHARACTER]; } else col = syntax_color[COL_BAD]; } if (type & (COM_WHOLE | STR_WHOLE | CHR_WHOLE)) { memset( attr, col, len ); return( col ); } char_count = (info->charnum && !(type & (CHR_WHOLE | CHR_END))); i = 0; /* * Skip leading blanks and test for preprocessor. */ if (!in_prepro && !in_comment && !in_string && !in_character) { for (; i < len && bj_isspace( text[i] ); ++i) attr[i] = col; this = (i < len) ? text[i] : '\0'; next = (i+1 < len) ? text[i+1] : '\0'; if ( info->prepro[0] && this == info->prepro[0] && (!info->prepro[1] || next == info->prepro[1])) { col = syntax_color[COL_PREPRO]; attr[i++] = col; if (info->prepro[1]) attr[i++] = col; in_prepro = TRUE; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -