📄 syntax.c
字号:
} if (errmsg != NULL) { key = ERROR; if (!in_macro && line_no > error_no) { ERRORLINE( errmsg, token ); error_no = line_no; } } } while (key == ERROR); return( key );}/* * Name: add_language * Purpose: add a language to the list * Passed: lang: the language to add * parent: parent language or NULL for no parent * Returns: pointer to new language on success; NULL on error (no memory) * * 980531: added the defaults. */LANGUAGE *add_language( char *lang, LANGUAGE *parent ){LANGUAGE *new_lang;syntax_info *info = NULL;int rc = OK;int len = strlen( lang ); new_lang = (LANGUAGE *)calloc( 1, sizeof(LANGUAGE) + len ); if (new_lang == NULL) rc = ERROR; else if (parent == NULL) { info = (syntax_info *)calloc( 1, sizeof(syntax_info) ); if (info == NULL) { rc = ERROR; free( new_lang ); } else new_lang->info = info; } else { new_lang->info = parent->info; new_lang->parent = parent; } if (rc == OK) { new_lang->next = g_status.language_list; g_status.language_list = new_lang; memcpy( new_lang->name, lang, len + 1 ); new_lang->key_tree.key = 0x10000L; /* * Use config setting for tab mode if this is not set. */ new_lang->inflate_tabs = ERROR; if (info != NULL) lang_defaults( info ); } else /* * out of memory */ error( WARNING, prompt_line, main4 ); return( rc == OK ) ? new_lang : NULL;}/* * Name: lang_defaults * Purpose: set default language information * Author: Jason Hood * Date: December 2, 2003 * Passed: info: information being set * Notes: assumes info has been cleared on entry */static void lang_defaults( syntax_info *info ){int j; /* * Characters have only one character (plus the closing quote character). */ info->charnum = 2; /* * Case sensitive. */ info->icase = MATCH; /* * Identifiers can start with a letter and contain letters and digits. * Digits are set with their appropriate bases. */ for (j = 0; j < 256; ++j) { if (bj_isalpha( j )) info->identifier[j] = ID_STARTWORD | ID_INWORD; else if (bj_isdigit( j )) info->identifier[j] = ID_INWORD | ID_DIGIT | ID_DECIMAL; if (bj_isxdigit( j )) info->identifier[j] |= ID_HEX | ID_DIGIT; } info->identifier[(int)'0'] |= ID_BINARY | ID_OCTAL; info->identifier[(int)'1'] |= ID_BINARY | ID_OCTAL; for (j = '2'; j < '8'; ++j) info->identifier[j] |= ID_OCTAL;}/* * Name: syntax_parse_file * Purpose: grab all the syntax highlighting info for a language * Passed: fp: file pointer of syntax file * syntax: place to store the info * Notes: reads from the current position till the next "language" or eof. * Some components are either setting it, or using it as a color for * a list of words (eg. "comment //", "comment rem"). If the first * character can start a word, assume the latter. This also implies * that startword should be done before keywords. * * 980531: moved the defaults to add_language. * 990426: turn in_macro off. * 990503: added the U macro for consistent array referencing. * 011122: expanded comments to four characters and allow two of each type. * 020623: fixed a bug in recognizing the second line comment. */#define U( c ) (text_t)(c)void syntax_parse_file( FILE *fp, LANGUAGE *syntax ){syntax_info *info = syntax->info;char key[1042]; /* buffer to hold any token that we parse */char *residue; /* pointer to next item in line, if it exists */int key_no; /* index into key array */char *number; /* pointer to one of the bases */int i, j; for (;;) { key_no = syntax_read_line( fp, &residue ); if (key_no == SHL_LANGUAGE || key_no == ERROR) break; if (key_no == SHL_MACRO) { parse_line( line_in, prompt_line ); while (process_macro) { if (syntax_read_line( fp, &residue ) == ERROR) { /* * Unexpected end of file. * Tidy up the macro definition. */ check_macro( mac ); error( WARNING, prompt_line, config26 ); } else parse_macro( line_in, prompt_line ); } in_macro = FALSE; continue; } else if (key_no == SHL_BACKGROUND) { key_no = parse_color( &residue, key, prompt_line, config6a ); if (key_no != ERROR) { key_no >>= 4; background = key_no & 15; } continue; } residue = parse_token( residue, key ); switch (key_no) { case SHL_PATTERN: /* * Setting is in the wrong place. */ ERRORLINE( syntax5, key ); break; case SHL_CASE: key_no = search( key, case_modes, 1 ); if (key_no == ERROR) { ERRORLINE( syntax6, key ); /* case setting not recognized */ } else { info->icase = key_no; sort.order_array = (key_no == MATCH) ? sort_order.match : sort_order.ignore; } break; case SHL_ESCAPE: if (strlen( key ) != 1 || bj_isalnum( *key )) { ERRORLINE( syntax7, key ); /* expecting one non-alphanumeric */ } else info->escape = *key; break; case SHL_STARTWORD: case SHL_INWORD: /* * Allow a range using '-', provided it's not at the beginning * or end of the key and the end-character is greater than the * start-character. */ key_no = (key_no == SHL_STARTWORD) ? ID_STARTWORD : ID_INWORD; while (*key) { for (i = 0; key[i]; ++i) { if (key[i] == '-' && (i != 0 && key[i+1] != '\0') && U( key[i+1] ) > U( key[i-1] )) { ++i; for (j = U( key[i-2] ) + 1; j < U( key[i] ); ++j) info->identifier[j] |= key_no; } info->identifier[U( key[i] )] |= key_no; } residue = parse_token( residue, key ); } break; case SHL_INNUMBER: /* * Different from the above in that numbers are case insensitive, * so transform both cases of a letter. */ key_no = ID_DIGIT | ID_BINARY | ID_OCTAL | ID_DECIMAL | ID_HEX; while (*key) { for (i = 0; key[i]; ++i) { if (key[i] == '-' && (i != 0 && key[i+1] != '\0') && U( key[i+1] ) > U( key[i-1] )) { ++i; for (j = U( key[i-2] + 1 ); j < U( key[i] ); ++j) { info->identifier[bj_tolower( j )] |= key_no; info->identifier[bj_toupper( j )] |= key_no; } } info->identifier[bj_tolower( key[i] )] |= key_no; info->identifier[bj_toupper( key[i] )] |= key_no; } residue = parse_token( residue, key ); } break; case SHL_COMMENT: if (info->identifier[U( *key )] & ID_STARTWORD) add_keyword_list( syntax, key_no, key, residue ); else { if (strlen( key ) > 4) { ERRORLINE( syntax8b, key ); /*only one to four chars allowed*/ /* * comment has two forms: "comment one" or "comment one two". * The first is a line comment; the second is the start and end * of a multi-line comment. */ } else { char com[5]; strcpy( com, key ); parse_token( residue, key ); if (*key) { if (strlen( key ) > 4) { ERRORLINE( syntax8b, key ); } else if (info->comstart[1][0] != '\0') { ERRORLINE( syntax14a, key ); } else { int com_num = (info->comstart[0][0] != '\0'); strcpy( (char *)info->comstart[com_num], com ); strcpy( (char *)info->comend[com_num], key ); } } else if (info->comment[1][0] != '\0') { ERRORLINE( syntax14b, key ); } else { int com_num = (info->comment[0][0] != '\0'); strcpy( (char *)info->comment[com_num], com ); } } } break; case SHL_FUNCTION: if (info->identifier[U( *key )] & ID_STARTWORD) add_keyword_list( syntax, key_no, key, residue ); else { if (strlen( key ) > 1) { ERRORLINE( syntax9, key ); /* only one char allowed */ } else info->function = *key; } break; case SHL_PREPRO: if (info->identifier[U( *key )] & ID_STARTWORD) add_keyword_list( syntax, key_no, key, residue ); else { if (strlen( key ) > 2) { ERRORLINE( syntax8a, key ); } else { info->prepro[0] = key[0]; info->prepro[1] = key[1]; residue = parse_token( residue, key ); if (*key && *key != ';') { if (search( key, valid_string, 1 ) != SHL_SPANLINE) { ERRORLINE( syntax5, key ); /* setting in wrong place */ } else { parse_token( residue, key ); if (strlen( key ) != 1 || bj_isalnum( *key )) { ERRORLINE( syntax7, key ); } else info->prepspan = *key; } } } } break; case SHL_BINARY: case SHL_OCTAL: case SHL_HEX: if ((info->identifier[U( *key )] & ID_STARTWORD) && (key[1] != '-' && key[2] != '-')) add_keyword_list( syntax, key_no, key, residue ); else { if (key_no == SHL_BINARY) number = (char *)info->binary; else if (key_no == SHL_OCTAL) number = (char *)info->octal; else number = (char *)info->hex; /* * The based numbers can have two forms: "base a[b]-" or * "base -a[b]". The former specifies a one- or two-character * prefix (eg. a[b]123); the latter is a suffix (123a[b]). */ residue = key; if (residue[0] == '-') { number[0] = SUFFIX; ++residue; } number[1] = bj_tolower( residue[0] ); if (residue[1] != '-') { number[2] = bj_tolower( residue[1] ); ++residue; } if (residue[1] != '-' && number[0] != SUFFIX) { ERRORLINE( syntax10, key ); /* requires prefix or suffix */ } else if (residue[1] == '-') { if (number[0] == SUFFIX) { ERRORLINE( syntax11, key ); /* can't be prefix & suffix */ } else number[0] = PREFIX; } } break; case SHL_STRING: if (info->identifier[U( *key )] & ID_STARTWORD) add_keyword_list( syntax, key_no, key, residue ); else { if (strlen( key ) > 2) { ERRORLINE( syntax8a, key ); } else { /* * Strings can have three forms: "string a", "string ab" or * "string a b". The first indicates that the open and close * quote character are the same. The other two specify the * quote characters individually. Strings can also have * "newline" and "spanline a" (where "a" is non-alphanumeric) * modifiers. */ if (key[1] == '\0') { info->strstart = key[0]; number = parse_token( residue, key ); if (key[0] != '\0' && key[1] == '\0') { info->strend = key[0]; residue = number; } else info->strend = info->strstart; } else { info->strstart = key[0]; info->strend = key[1]; } for (;;) { residue = parse_token( residue, key ); if (*key == '\0' || *key == ';') break; key_no = search( key, valid_string, 1 ); if (key_no == ERROR) { ERRORLINE( syntax5, key ); continue; } if (key_no == SHL_NEWLINE)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -