⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 syntax.c

📁 一个开源著名的TDE编辑器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Editor:      TDE, the Thomson-Davis Editor * Filename:    syntax.c * Author:      Jason Hood * Date:        August 30, 1997 to September 13 * * All the syntax highlighting functions. * * My implementation of syntax highlighting is a hybrid of Elvis', by Steve * Kirkendall, and Rhide's, by Salvador E. Tropea and Robert Hoehne. * * There are four stages for a file to have syntax highlighting: locate the * language, parse it, set the initial flags, and finally display it. The * languages are in the "tde.shl" (_S_yntax _H_igh_L_ighting) file. If it can't * be found in the current directory, try HOME or the executable's directory * before giving up. The file is then parsed and syntatic features and keywords * (or just words to be highlighted) are noted. That's what I borrowed from * Elvis. When Elvis displays lines, it searches backwards to see if it's in a * comment or string. I didn't really like this idea, so I decided to use * Rhide's method of storing the type of each line. It's only required for the * multi-line stuff - everything else can be calculated on the fly. (The types * are explained in syntax_check()). To display lines requires re-calculating * the type of this line (since it's probably been modified), checking if that * would affect other lines (eg. starting a multi-line comment) and finally * displaying all the affected lines. The actual display is still done in * update_line(), but the checking is done here, as is determining what color * each character of the line will be (the syntax_attr() function). * * I was wondering how to handle C's 'l', 'u' and 'f' suffixes. Initially I was * going to handle it specially, along with Pascal and Ada's '#' character * (character constant for Pascal, based number for Ada). Later I realized that * PERL and Ada can have underscores in their numbers, so I added the "innumber" * command. It's not a perfect solution, but it's better to have invalid numbers * in the integer color, rather than valid numbers in bad. * * 980531: look for the syntax file in the HOME/executable directory and then *          the current directory. This allows languages to be defined globally *          with local add-ons. * 980716: made the language and keyword strings use FAR pointers; as a *          consequence use of my_{malloc,strcmp,free}. * 980813: Allow languages to "inherit" from another language; the current *          directory is again scanned first. * 990426: allocated the language name as part of the structure. * 011122: allow two of each comment type, using four characters maximum. */#include "tdestr.h"     /* typedefs for global variables */#include "common.h"#include "define.h"     /* editor function defs */#include "tdefunc.h"    /* prototypes for all functions in tde */#include "syntax.h"     /* syntax highlighting definitions */#include "config.h"     /* syntax highlighting file processing */#define NO_LANGUAGE     -2      /* return codes for scan_syntax */#define LANGUAGE_EXISTS  1/* * Some globals for file parsing. */static int  initialized = FALSE; /* have the colors been defined? */static file_infos *syntax_file; /* file containing syntax highlighting */static int  rescan = FALSE;     /* rescan an already loaded language */extern char *line_in;           /* input line buffer */extern char line_out[];         /* output line buffer */extern int  line_no;            /* current line number */static int  error_no = 0;       /* errors before this already displayed */extern int  process_macro;extern MACRO *mac;extern TREE *branch;extern TREE *cfg_key_tree;static int  prompt_line;static int  in_macro = FALSE;extern int  background;extern MENU_STR *user_menu;extern void make_menu( MENU_STR *, long *, int );static int  out_of_memory;      /* no room for keywords */static void lang_defaults( syntax_info * );static int  language_list( char * );static void find_languages( char *, LIST **, int * );/* * Name:    init_syntax * Purpose: see if the file has a recognized language; if so initialise *           the syntax highlighting. * Passed:  window: pointer to current window * Returns: OK for a recognized language; *          NO_LANGUAGE for no recognized language/pattern; *          ERROR otherwise. * Notes:   if g_option.language is NULL, test the filename for a pattern; *           if empty (ie "") then syntax highlighting is disabled; *           otherwise load the language specified. If it couldn't be found *           set g_option.language to NULL. * * 980526:  Modified to suit the changed syntax_select. * 031128:  Ignore non-file windows. */int init_syntax( TDE_WIN *window ){LANGUAGE *ll;char fname[PATH_MAX];           /* location of syntax highlighting file */int  rc;   if (g_option.language && *g_option.language == '\0')      return( NO_LANGUAGE );   syntax_file = window->file_info;   if (!g_option.language && syntax_file->file_name[0] == '\0')      return( NO_LANGUAGE );   /*    * See if the language has already been loaded.    */   sort.order_array = sort_order.ignore;   if (g_option.language && !rescan) {      for (ll = g_status.language_list; ll != NULL; ll = ll->next) {         if (!my_strcmp( (text_ptr)g_option.language, (text_ptr)ll->name ))            break;      }      if (ll != NULL) {         syntax_file->syntax = ll;         syntax_init_lines( syntax_file );         window->syntax = TRUE;         return( OK );      }   }   prompt_line = window->bottom_line;   out_of_memory = FALSE;   rc = NO_LANGUAGE;   if (file_exists( SYNTAXFILE ) == 0)      rc = scan_syntax( SYNTAXFILE, g_option.language, TRUE );   if (rc == NO_LANGUAGE) {      join_strings( fname, g_status.argv[0], SYNTAXFILE );      rc = scan_syntax( fname, g_option.language, FALSE );   }      if (rc == OK)      syntax_init_lines( syntax_file );   else if (rc == NO_LANGUAGE && g_option.language) {      combine_strings( line_out, syntax13a, g_option.language, syntax13b );      error( WARNING, prompt_line, line_out );      if (g_option.language == g_option_all.language)         g_option_all.language = NULL;   }   /*    * Don't turn off syntax highlighting if the new language wasn't found.    */   if (!window->syntax)      window->syntax = (rc == OK) ? TRUE : FALSE;   return( rc );}/* * Name:    scan_syntax * Purpose: to determine if the file should have syntax highlighting * Passed:  name:     name of the syntax highlighting file *          language: language to find, or NULL to match filename pattern *          local:    is the syntax file in the current directory? * Returns: OK if the file has syntax highlighting; *          NO_LANGUAGE if the language couldn't be identified; *          ERROR otherwise (no memory). * * 980526:  Modified to suit the changed syntax_select. * 980815:  If the file is local, prepend the current directory to each pattern. */int scan_syntax( char *name, char *language, int local ){FILE *fp;char *line;                     /* pointer to the line read */char lang[MAX_COLS+2];          /* buffer to hold the language found */char parent[MAX_COLS+2];        /* buffer for the parent language */char dir[PATH_MAX];             /* buffer for current directory/pattern */char *pat;                      /* pointer into above for pattern */int  key_no;                    /* index into key array */register LANGUAGE *ll;          /* list of languages already loaded */int  rc = NO_LANGUAGE;int  load = TRUE;unsigned old_line;int  cnt;   /*    * Open the file in binary mode, since I seek in syntax_init_colors().    */   if ((fp = fopen( name, "rb" )) == NULL)      return( NO_LANGUAGE );   sort.order_array = sort_order.ignore;   if (local) {      get_current_directory( dir );      if (!strcmp( dir, g_status.argv[0] )) {         *dir  = '\0';         local = FALSE;      }   } else      *dir = '\0';   pat = dir + strlen( dir );   line_no = 0;   process_macro = FALSE;   while (rc == NO_LANGUAGE) {      do         key_no = syntax_read_line( fp, &line );      while (key_no != SHL_LANGUAGE && key_no != ERROR);      if (key_no == ERROR)         break;      line = parse_token( line, lang );      if (language != NULL) {         if (!my_strcmp( (text_ptr)lang, (text_ptr)language ))            rc = OK;         else            continue;      }      /*       * Search for the parent language       */      if (line != NULL) {         /*          * Skip the optional "from"          */         line = parse_token( line, parent );         if (line != NULL)            parse_token( line, parent );      } else         *parent = '\0';      key_no = syntax_read_line( fp, &line );      if (key_no == SHL_PATTERN) {         while (rc == NO_LANGUAGE && line != NULL) {            line = parse_token( line, pat );            if (wildcard( dir, syntax_file->file_name ))               rc = OK;         }      } else if (line_no > error_no) {         ERRORLINE( syntax2, lang );    /* expecting pattern after language */         error_no = line_no;      }   }   if (rc == OK) {      for (ll = g_status.language_list; ll != NULL; ll = ll->next) {         if (!my_strcmp( (text_ptr)lang, (text_ptr)ll->name ))            break;      }      if (ll == NULL) {         if (*parent) {            rescan = FALSE;            old_line = line_no;            rc = scan_syntax( name, parent, local );            if (rc == NO_LANGUAGE && local) {               join_strings( dir, g_status.argv[0], SYNTAXFILE );               rc = scan_syntax( dir, parent, FALSE );            }            line_no = old_line;            if (rc == OK) {               ll = add_language( lang, syntax_file->syntax );               if (ll == NULL)                  load = FALSE;               else                  syntax_file->syntax = ll;            } else if (rc == NO_LANGUAGE) {               load = FALSE;               combine_strings( line_out, syntax13a, parent, syntax13b );               ERRORLINE( line_out, dir );            }         } else {            if ((ll = add_language( lang, NULL )) == NULL) {               rc   = ERROR;               load = FALSE;            } else               syntax_file->syntax = ll;         }      } else {         syntax_file->syntax = ll;         load = rescan;      }      if (load) {         cfg_key_tree = &ll->key_tree;         user_menu = &ll->menu;         if (user_menu->minor_cnt == 0  &&             ll->parent && ll->parent->menu.minor_cnt != 0) {            /*             * Make a duplicate of the parent's menu.             */            cnt = user_menu->minor_cnt = ll->parent->menu.minor_cnt;            cnt *= sizeof(MINOR_STR);            user_menu->minor = malloc( cnt );            if (user_menu->minor != NULL) {               memcpy( user_menu->minor, ll->parent->menu.minor, cnt );               user_menu->minor->line = NULL;            }         }         /*          * A new language is being loaded. If this is the first language          * initialize all the colors.          */         if (!initialized) {            syntax_init_colors( fp );            initialized = TRUE;         }         if (ll->info->icase == MATCH)            sort.order_array = sort_order.match;         syntax_parse_file( fp, syntax_file->syntax );         if (user_menu->minor_cnt != 0) {            get_minor_counts( user_menu );            make_menu( user_menu, NULL, 1 );         }      }   }   fclose( fp );   return( rc );}/* * Name:    syntax_read_line * Purpose: read a line from the syntax file * Passed:  fp:   file to read *          line: pointer to the next token * Returns: the key number of the first token, or ERROR for eof or error. *          line points past the first token, or NULL for eof or error. * Notes:   global variable line_no is updated. *          blank lines and comments are skipped. *          unrecognized settings display a warning but continue. *          macros ignore lines until another valid syntax feature. * * 980526:  if the second last character is '\r', make it '\n'. * 990421:  recognize new color parsing. */int  syntax_read_line( FILE *fp, char **line ){char token[1042];int  key;const char *errmsg;   do {      errmsg = NULL;      do {         ++line_no;         if ((key = read_line( fp )) == EOF) {            *line = NULL;            return( ERROR );         }#if !defined( __UNIX__ )         /*          * need to remove the CR manually, since I'm reading as binary          */         if (line_in[key-1] == '\r')            line_in[key-1] = '\0';#endif         *line = parse_token( line_in, token );      } while (*token == '\0');      if (process_macro)         return( SHL_MACRO );      if (*line == NULL)         errmsg = config1;      /* setting without value */      else {         key = search( token, valid_syntax, SHL_NUM_FEATURES-1 );         if (key != ERROR)            in_macro = (key == SHL_MACRO);         else if (!in_macro) {            key = parse_key( token );            if (key != ERROR) {               if (key_func[KEY_IDX( key )] != TwoCharKey)                  errmsg = syntax4;     /* syntax macro requires two-key */               else {                  key = SHL_MACRO;                  in_macro = TRUE;               }            } else {               *line = line_in;               key = parse_color( line, token, prompt_line, syntax1 );            }         }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -