evil-qemacs/lang/agena.c
Charlie Gordon e3c5bfd457
Remove references to global qe_state (#45)
* Remove references to global `qe_state`

Add `QEmacsState *qs` field in context and object structures:
- `QEditScreen`, `EditState` (renamed from `qe_state`), `QuitState`
- `WinWindow` (win32.c), `X11State` (x11.c), `QEArgs` (cmd line arguments)
- `CmdLineOptionDef::func_arg()`, `QEModeData`
- move `QEKeyContext` to `QEmacsState`

Pass `QEmacsState *qs` to configuration and state functions:
- all `module_xxx_init` and static `xxx_init` functions
- `QEDisplay::dpy_init()`, `qe_register_display()`, `screen_init()̀`
- `load_input_methods()`, `unload_input_methods()`
- `register_input_method()`, `find_input_method()`
- `find_resource_file()`, `open_resource_file()`
- `qe_find_current_binding()`, `qe_list_bindings()`
- `qe_register_mode()`, `qe_find_mode()`, `qe_find_mode_filename()`
- `qe_register_cmd_line_options()`, `set_user_option()`, `set_tty_charset()`
- `qe_register_commands()`, `qe_register_bindings()`, `qe_find_cmd()`
- `qe_register_completion()`, `qe_register_variables()`
- `eb_register_data_type()`, `parse_command_line()`
- `eb_trace_bytes()`, `qe_toggle_control_h()` (split from `do_toggle_control_h()`)
- `unget_key()`, `qe_grab_keys()`, `qe_ungrab_keys()`, `qe_key_process()`
- `eb_new()`, `eb_find()`, `eb_find_new()`, `eb_scratch()`, `eb_find_file()`
- `new_shell_buffer()` `macro_add_key()`, `clear_macro(), `stop_macro()`
- `check_window()`, `check_buffer()`, `qe_kill_buffer()`, `qe_get_history()`
- `qe_register_charset()`, `find_charset()`

Add error message handlers:
- add `QEDisplay::dpy_error()` method
- add `qe_cfg_error()`, use for all expression parsing errors
- pass opaque pointer to `css_error()`
- add `qe_put_error()` and `qe_dpy_error()`

Add context argument:
- always pass a non-null window pointer to `do_refresh()`, `new_help_buffer()`

Rename functions:
- `find_resource_file` -> `qe_find_resource_file`
- `open_resource_file` -> `qe_open_resource_file`
- `input_methods_init` -> `qe_input_methods_init`
- `load_input_methods` -> `qe_load_input_methods`
- `unload_input_methods` -> `qe_unload_input_methods`
- `find_input_methods` -> `qe_find_input_methods`
- `register_input_method` -> `qe_register_input_method`
- `parse_command_line` -> `qe_parse_command_line`
- `eb_trace_bytes` -> `qe_trace_bytes`
- `eb_init` -> `qe_data_init`
- `eb_count_buffers` -> `qe_count_buffers`
- `eb_get_buffer_from_index` -> `qe_get_buffer_from_index`
- `init_all_modules` -> `qe_init_all_modules`
- `exit_all_modules` -> `qe_exit_all_modules`
- `load_all_modules` -> `qe_load_all_modules`
- `maybe_set_mark` -> `do_maybe_set_mark`
- `unget_key` -> `qe_unget_key`
- `minibuffer_init` -> `qe_minibuffer_init`
- `edit_display` -> `qe_display`
- `new_yank_buffer` -> `qe_new_yank_buffer`
- `new_shell_buffer` -> `qe_new_shell_buffer`
- `shell_find_mode` -> `qe_shell_find_mode`
- `save_selection` -> `qe_save_selection`
- `register_emulation_bindings` -> `qe_register_emulation_bindings`
- `macro_add_key` -> `qe_macro_add_key`
- `clear_macro` -> `qe_clear_macro`
- `stop_macro` -> `qe_stop_macro`
- `eb_format_message` -> `qe_format_message`
- `screen_init` -> `qe_screen_init`
- `charset_jis_init` -> `qe_charset_jis_init`
- `charset_more_init` -> `qe_charset_more_init`
- `check_window` -> `qe_check_window`
- `check_buffer` -> `qe_check_buffer`
- `eb_find_file` -> `qe_find_buffer_file`
- `eb_find` -> `qe_find_buffer_name`
- `eb_new` -> `qe_new_buffer`
- `eb_find_new` -> `qe_new_buffer` with `BC_REUSE`
- `eb_scratch` -> `qe_new_buffer` with `BC_REUSE | BC_CLEAR`
- `find_charset` -> `qe_find_charset`

Add asan, msan and ubsan targets
Fix `qe_encode64` buffer length computation.
Add `qe_new_shell_buffer` flags `SF_REUSE_BUFFER` and `SF_ERASE_BUFFER`
Bumped version to 6.3.3
fix redundant typedef
fix compilation errors
2024-12-01 23:34:00 +01:00

206 lines
6.9 KiB
C

/*
* Agena language mode for QEmacs.
*
* Copyright (c) 2000-2024 Charlie Gordon.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "qe.h"
/*---------------- AGENA script coloring ----------------*/
#define AGN_SHORTSTRINGDELIM " ,~[]{}();:#'=?&%$\xA7\\!^@<>|\r\n\t"
enum {
IN_AGENA_COMMENT = 0x01,
IN_AGENA_STRING1 = 0x02,
IN_AGENA_STRING2 = 0x04,
};
enum {
AGENA_STYLE_TEXT = QE_STYLE_DEFAULT,
AGENA_STYLE_COMMENT = QE_STYLE_COMMENT,
AGENA_STYLE_STRING = QE_STYLE_STRING,
AGENA_STYLE_NUMBER = QE_STYLE_NUMBER,
AGENA_STYLE_KEYWORD = QE_STYLE_KEYWORD,
AGENA_STYLE_TYPE = QE_STYLE_TYPE,
AGENA_STYLE_FUNCTION = QE_STYLE_FUNCTION,
AGENA_STYLE_IDENTIFIER = QE_STYLE_DEFAULT,
};
static char const agena_keywords[] = {
/* abs alias and antilo2 antilog10 arccos arcsec arcsin arctan as
assigned atendof bea bottom break by bye case catch char cis clear cls
conjugate copy cos cosh cosxx create dec delete dict div do downto
duplicate elif else end entier enum esac even exchange exp fail false fi
filled first finite flip for from global if imag import in inc infinity
insert int intersect into is join keys last left ln lngamma local lower
minus mul nan nand nargs nor not numeric od of onsuccess or pop proc
qmdev qsadd real redo reg relaunch replace restart return right rotate
sadd seq shift sign signum sin sinc sinh size skip smul split sqrt
subset tan tanh then to top trim true try type typeof unassigned
undefined union unique until upper values when while xor xsubset
yrt */
/* keywords */
"|alias|as|bottom|break|by|case|catch|clear|cls|create|dec|delete"
"|dict|div|do|duplicate|elif|else|end|enum|epocs|esac|external|exchange"
"|fi|for|from|if|import|inc|insert|into|is|keys|mul|nargs"
"|od|of|onsuccess|pop|proc|quit|redo|reg|relaunch|return|rotate"
"|scope|seq|skip|then|try|to|top|try|until|varargs"
"|when|while|yrt"
"|readlib"
/* constants */
"|infinity|nan|I"
/* operators */
"|or|xor|nor|and|nand|in|subset|xsubset|union|minus|intersect|atendof"
"|split|shift|not"
"|assigned|unassigned|size|type|typeof|left|right|filled|finite"
"|"
};
static char const agena_types[] = {
"|boolean|complex|lightuserdata|null|number|pair|register|procedure"
"|sequence|set|string|table|thread|userdata"
"|global|local|char|float|undefined|true|false|fail"
"|"
};
static void agena_colorize_line(QEColorizeContext *cp,
const char32_t *str, int n,
QETermStyle *sbuf, ModeDef *syn)
{
char kbuf[16];
int i = 0, start = i, style = 0;
int state = cp->colorize_state;
char32_t c, sep = 0;
if (state & IN_AGENA_COMMENT)
goto parse_block_comment;
if (state & IN_AGENA_STRING1)
goto parse_string1;
if (state & IN_AGENA_STRING2)
goto parse_string2;
while (i < n) {
start = i;
c = str[i++];
switch (c) {
case '#':
if (str[i] == '/') {
/* block comment */
i++;
parse_block_comment:
state |= IN_AGENA_COMMENT;
for (; i < n; i++) {
if (str[i] == '/' && str[i + 1] == '#') {
i += 2;
state &= ~IN_AGENA_COMMENT;
break;
}
}
} else {
i = n;
}
style = AGENA_STYLE_COMMENT;
break;
case '\"':
state = IN_AGENA_STRING2;
parse_string2:
sep = '\"';
goto parse_string;
case '\'':
state = IN_AGENA_STRING1;
parse_string1:
sep = '\'';
/* parse string const */
parse_string:
for (; i < n; i++) {
if (str[i] == '\\' && i + 1 < n) {
i++;
continue;
}
if (str[i] == sep) {
state = 0;
i++;
break;
}
}
style = AGENA_STYLE_STRING;
break;
case '`': /* short string */
while (i < n && !qe_findchar(AGN_SHORTSTRINGDELIM, str[i]))
i++;
style = AGENA_STYLE_IDENTIFIER;
break;
default:
/* parse identifiers and keywords */
if (qe_isalpha_(c)) {
i += ustr_get_identifier(kbuf, countof(kbuf), c, str, i, n);
if (strfind(syn->keywords, kbuf))
style = AGENA_STYLE_KEYWORD;
else
if (strfind(syn->types, kbuf))
style = AGENA_STYLE_TYPE;
else
if (check_fcall(str, i))
style = AGENA_STYLE_FUNCTION;
else
style = AGENA_STYLE_IDENTIFIER;
break;
}
if (qe_isdigit(c) || (c == '.' && qe_isdigit(str[i]))) {
while (qe_isdigit_(str[i]) || str[i] == '\'' || str[i] == '.')
i++;
if (qe_findchar("eE", str[i])) {
i++;
if (qe_findchar("+-", str[i]))
i++;
}
while (qe_isalnum(str[i]))
i++;
style = AGENA_STYLE_NUMBER;
break;
}
continue;
}
if (style) {
SET_STYLE(sbuf, start, i, style);
style = 0;
}
}
cp->colorize_state = state;
}
static ModeDef agena_mode = {
.name = "Agena",
.extensions = "agn",
.keywords = agena_keywords,
.types = agena_types,
.colorize_func = agena_colorize_line,
};
static int agena_init(QEmacsState *qs)
{
qe_register_mode(qs, &agena_mode, MODEF_SYNTAX);
return 0;
}
qe_module_init(agena_init);