add cast to XtCalloc() call
[nedit-bw.git] / define_macro.patch
blob678ceeef1f289be4da4928c9ae3b86c083b7da8f
1 Subject: define() macro
3 This lets you define a new function in runtime.
5 With the "override" option you can override preexisting macro functions, but
6 only macro functions, no action routines nor c functions.
8 ---
10 doc/help.etx | 5 ++
11 source/highlightData.c | 2
12 source/macro.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++
13 source/parse.y | 2
14 4 files changed, 107 insertions(+), 2 deletions(-)
16 diff --quilt old/source/macro.c new/source/macro.c
17 --- old/source/macro.c
18 +++ new/source/macro.c
19 @@ -440,10 +440,13 @@ static int dictsaveMS(WindowInfo *window
20 static int dictappendMS(WindowInfo *window, DataValue *argList, int nArgs,
21 DataValue *result, char **errMsg);
22 static int dictiselementMS(WindowInfo *window, DataValue *argList, int nArgs,
23 DataValue *result, char **errMsg);
25 +static int defineMS(WindowInfo *window, DataValue *argList, int nArgs,
26 + DataValue *result, char **errMsg);
28 /* Built-in subroutines and variables for the macro language */
29 static const BuiltInSubrName MacroSubrs[] = {
30 { "length", lengthMS },
31 { "get_range", getRangeMS },
32 { "t_print", tPrintMS },
33 @@ -506,10 +509,11 @@ static const BuiltInSubrName MacroSubrs[
34 { "dict_insert", dictinsertMS },
35 { "dict_complete", dictcompleteMS },
36 { "dict_save", dictsaveMS },
37 { "dict_append", dictappendMS },
38 { "dict_is_element", dictiselementMS },
39 + { "define", defineMS },
40 { NULL, NULL } /* sentinel */
43 static const BuiltInSubrName SpecialVars[] = {
44 { "$cursor", cursorMV },
45 @@ -3607,10 +3611,106 @@ static int callMS(WindowInfo *window, Da
46 return False;
48 return OverlayRoutineFromSymbol(sym, nArgs, 1);
51 +/*
52 + * define(func_name, func_body[, "override"])
53 + */
54 +static int defineMS(WindowInfo *window, DataValue *argList, int nArgs,
55 + DataValue *result, char **errMsg)
57 + char stringStorage[3][TYPE_INT_STR_SIZE(int)];
58 + char *name = NULL;
59 + char *body = NULL;
60 + char *bodysave = NULL;
61 + char *stoppedAt = NULL;
62 + char *namePtr;
63 + char *override = NULL;
64 + Program *prog;
65 + Symbol *sym;
66 + DataValue subrPtr;
68 + if (nArgs < 2 || nArgs > 3) {
69 + return wrongNArgsErr(errMsg);
70 + }
71 + if (!readStringArg(argList[0], &name, stringStorage[0], errMsg)) {
72 + return False;
73 + }
74 + if (!readStringArg(argList[1], &body, stringStorage[1], errMsg)) {
75 + return False;
76 + }
77 + if (nArgs > 2) {
78 + if (!readStringArg(argList[2], &override, stringStorage[2], errMsg)) {
79 + return False;
80 + }
81 + if (strcmp(override, "override")) {
82 + *errMsg = "Unknown parameter for subroutine %s";
83 + return False;
84 + }
85 + }
87 + /* check function name */
88 + if (strlen(name) > MAX_SYM_LEN ||
89 + (!isalpha((unsigned char)name[0]) && !name[0] != '$')) {
90 + *errMsg = "subroutine name is not a valid identifier";
91 + return False;
92 + }
93 + namePtr = name + 1;
94 + while (isalnum((unsigned char)*namePtr) || *namePtr == '_')
95 + namePtr++;
96 + if (*namePtr) {
97 + *errMsg = "subroutine name is not a valid identifier";
98 + return False;
99 + }
101 + /* add a terminating newline */
102 + bodysave = XtMalloc(strlen(body) + 2);
103 + if (!bodysave) {
104 + *errMsg = "Internal error";
105 + return False;
107 + strcpy(bodysave, body);
108 + strcat(bodysave, "\n");
110 + /* Parse the macro and report errors if it fails */
111 + prog = ParseMacro(bodysave, errMsg, &stoppedAt, False, name);
112 + if (!prog) {
113 + ParseError(window->macroCmdData ? window->shell : NULL,
114 + bodysave, stoppedAt, name, *errMsg);
115 + XtFree(bodysave);
116 + return False;
118 + XtFree(bodysave);
120 + sym = LookupSymbol(name);
121 + if (sym) {
122 + if (!override) {
123 + FreeProgram(prog);
124 + *errMsg = "Try to override existing function.";
125 + return False;
126 + } else {
127 + if (sym->type != MACRO_FUNCTION_SYM) {
128 + FreeProgram(prog);
129 + *errMsg = "Try to override a non macro function.";
130 + return False;
132 + /* its unsafe to free the old program,
133 + ** maybe it is currently in use
134 + */
135 + /* FreeProgram(sym->value.val.prog); */
136 + sym->value.val.prog = prog;
138 + } else {
139 + subrPtr.tag = NO_TAG;
140 + subrPtr.val.prog = prog;
141 + sym = InstallSymbol(name, MACRO_FUNCTION_SYM, subrPtr);
144 + return True;
147 /* T Balinski */
148 static int listDialogMS(WindowInfo *window, DataValue *argList, int nArgs,
149 DataValue *result, char **errMsg)
151 macroCmdInfo *cmdData;
152 diff --quilt old/source/highlightData.c new/source/highlightData.c
153 --- old/source/highlightData.c
154 +++ new/source/highlightData.c
155 @@ -549,11 +549,11 @@ static char *DefaultPatternSets[] = {
156 README:\"NEdit Macro syntax highlighting patterns, version 2.6, maintainer Thorsten Haude, nedit at thorstenhau.de\":::Flag::D\n\
157 Comment:\"#\":\"$\"::Comment::\n\
158 Built-in Misc Vars:\"(?<!\\Y)\\$(?:active_pane|args|calltip_ID|column|cursor|display_width|empty_array|file_name|file_path|language_mode|line|locked|max_font_width|min_font_width|modified|n_display_lines|n_panes|rangeset_list|read_only|selection_(?:start|end|left|right)|server_name|text_length|top_line|transient|VERSION|NEDIT_HOME)>\":::Identifier::\n\
159 Built-in Pref Vars:\"(?<!\\Y)\\$(?:auto_indent|em_tab_dist|file_format|font_name|font_name_bold|font_name_bold_italic|font_name_italic|highlight_syntax|incremental_backup|incremental_search_line|make_backup_copy|match_syntax_based|overtype_mode|show_line_numbers|show_matching|statistics_line|tab_dist|use_tabs|wrap_margin|wrap_text)>\":::Identifier2::\n\
160 Built-in Special Vars:\"(?<!\\Y)\\$(?:[1-9]|list_dialog_button|n_args|read_status|search_end|shell_cmd_status|string_dialog_button|sub_sep)>\":::String1::\n\
161 - Built-in Subrs:\"<(?:append_file|beep|call|calltip|clipboard_to_string|dialog|filename_dialog|dict_(?:insert|complete|save|append|is_element)|focus_window|get_character|get_matching|get_pattern_(by_name|at_pos)|get_range|get_selection|get_style_(by_name|at_pos)|getenv|highlight_calltip_line|kill_calltip|length|list_dialog|max|min|rangeset_(?:add|create|destroy|get_by_name|includes|info|invert|range|set_color|set_mode|set_name|subtract)|read_file|replace_in_string|replace_range|replace_selection|replace_substring|search|search_string|select|select_rectangle|set_cursor_pos|set_transient|shell_command|split|string_compare|string_dialog|string_to_clipboard|substring|t_print|tolower|toupper|valid_number|write_file)(?=\\s*\\()\":::Subroutine::\n\
162 + Built-in Subrs:\"<(?:append_file|beep|call|calltip|clipboard_to_string|define|dialog|filename_dialog|dict_(?:insert|complete|save|append|is_element)|focus_window|get_character|get_matching|get_pattern_(by_name|at_pos)|get_range|get_selection|get_style_(by_name|at_pos)|getenv|highlight_calltip_line|kill_calltip|length|list_dialog|max|min|rangeset_(?:add|create|destroy|get_by_name|includes|info|invert|range|set_color|set_mode|set_name|subtract)|read_file|replace_in_string|replace_range|replace_selection|replace_substring|search|search_string|select|select_rectangle|set_cursor_pos|set_transient|shell_command|split|string_compare|string_dialog|string_to_clipboard|substring|t_print|tolower|toupper|valid_number|write_file)(?=\\s*\\()\":::Subroutine::\n\
163 Menu Actions:\"<(?:new(?:_tab|_opposite)?|open|open-dialog|open_dialog|open-selected|open_selected|close|save|save-as|save_as|save-as-dialog|save_as_dialog|revert-to-saved|revert_to_saved|revert_to_saved_dialog|include-file|include_file|include-file-dialog|include_file_dialog|load-macro-file|load_macro_file|load-macro-file-dialog|load_macro_file_dialog|load-tags-file|load_tags_file|load-tags-file-dialog|load_tags_file_dialog|unload_tags_file|load_tips_file|load_tips_file_dialog|unload_tips_file|print|print-selection|print_selection|exit|undo|redo|delete|select-all|select_all|shift-left|shift_left|shift-left-by-tab|shift_left_by_tab|shift-right|shift_right|shift-right-by-tab|shift_right_by_tab|find|find-dialog|find_dialog|find-again|find_again|find-selection|find_selection|find_incremental|start_incremental_find|replace|replace-dialog|replace_dialog|replace-all|replace_all|replace-in-selection|replace_in_selection|replace-again|replace_again|replace_find|replace_find_same|replace_find_again|goto-line-number|goto_line_number|goto-line-number-dialog|goto_line_number_dialog|goto-selected|goto_selected|mark|mark-dialog|mark_dialog|goto-mark|goto_mark|goto-mark-dialog|goto_mark_dialog|match|select_to_matching|goto_matching|find-definition|find_definition|show_tip|split-pane|split_pane|close-pane|close_pane|detach_document(?:_dialog)?|move_document_dialog|(?:next|previous|last)_document|uppercase|lowercase|fill-paragraph|fill_paragraph|control-code-dialog|control_code_dialog|filter-selection-dialog|filter_selection_dialog|filter-selection|filter_selection|execute-command|execute_command|execute-command-dialog|execute_command_dialog|execute-command-line|execute_command_line|shell-menu-command|shell_menu_command|macro-menu-command|macro_menu_command|bg_menu_command|post_window_bg_menu|post_tab_context_menu|beginning-of-selection|beginning_of_selection|end-of-selection|end_of_selection|repeat_macro|repeat_dialog|raise_window|focus_pane|set_statistics_line|set_incremental_search_line|set_show_line_numbers|set_auto_indent|set_wrap_text|set_wrap_margin|set_highlight_syntax|set_make_backup_copy|set_incremental_backup|set_show_matching|set_match_syntax_based|set_overtype_mode|set_locked|set_tab_dist|set_em_tab_dist|set_use_tabs|set_fonts|set_language_mode)(?=\\s*\\()\":::Subroutine::\n\
164 Text Actions:\"<(?:self-insert|self_insert|grab-focus|grab_focus|extend-adjust|extend_adjust|extend-start|extend_start|extend-end|extend_end|secondary-adjust|secondary_adjust|secondary-or-drag-adjust|secondary_or_drag_adjust|secondary-start|secondary_start|secondary-or-drag-start|secondary_or_drag_start|process-bdrag|process_bdrag|move-destination|move_destination|move-to|move_to|move-to-or-end-drag|move_to_or_end_drag|end_drag|copy-to|copy_to|copy-to-or-end-drag|copy_to_or_end_drag|exchange|process-cancel|process_cancel|paste-clipboard|paste_clipboard|copy-clipboard|copy_clipboard|cut-clipboard|cut_clipboard|copy-primary|copy_primary|cut-primary|cut_primary|newline|newline-and-indent|newline_and_indent|newline-no-indent|newline_no_indent|delete-selection|delete_selection|delete-previous-character|delete_previous_character|delete-next-character|delete_next_character|delete-previous-word|delete_previous_word|delete-next-word|delete_next_word|delete-to-start-of-line|delete_to_start_of_line|delete-to-end-of-line|delete_to_end_of_line|forward-character|forward_character|backward-character|backward_character|key-select|key_select|process-up|process_up|process-down|process_down|process-shift-up|process_shift_up|process-shift-down|process_shift_down|process-home|process_home|forward-word|forward_word|backward-word|backward_word|forward-paragraph|forward_paragraph|backward-paragraph|backward_paragraph|beginning-of-line|beginning_of_line|end-of-line|end_of_line|beginning-of-file|beginning_of_file|end-of-file|end_of_file|next-page|next_page|previous-page|previous_page|page-left|page_left|page-right|page_right|toggle-overstrike|toggle_overstrike|scroll-up|scroll_up|scroll-down|scroll_down|scroll_left|scroll_right|scroll-to-line|scroll_to_line|select-all|select_all|deselect-all|deselect_all|focusIn|focusOut|process-return|process_return|process-tab|process_tab|insert-string|insert_string|mouse_pan)(?=\\s*\\()\":::Subroutine::\n\
165 Macro Hooks:\"<(?:(?:pre|post)_(?:open|save)|cursor_moved|modified|(?:losing_)?focus)_hook(?=\\s*\\()\":::Subroutine1::\n\
166 Keyword:\"<(?:break|continue|define|delete|else|for|if|in|return|typeof|while)>\":::Keyword::\n\
167 Braces:\"[{}\\[\\]]\":::Keyword::\n\
168 diff --quilt old/doc/help.etx new/doc/help.etx
169 --- old/doc/help.etx
170 +++ new/doc/help.etx
171 @@ -2688,10 +2688,15 @@ Macro Subroutines
173 **clipboard_to_string()**
174 Returns the contents of the clipboard as a macro string. Returns empty
175 string on error.
177 +**define( name, body [, "override"] )**
178 + Defines a new function with name ~name~ and the macro code in ~body~.
179 + If the ~"override"~ option is given the new symbol overrides previously
180 + defined functions.
182 **dialog( message, btn_1_label, btn_2_label, ... )**
183 Pop up a dialog for querying and presenting information to the user. First
184 argument is a string to show in the message area of the dialog.
185 Additional optional arguments represent labels for buttons to appear along
186 the bottom of the dialog. Returns the number of the button pressed (the
187 diff --quilt old/source/parse.y new/source/parse.y
188 --- old/source/parse.y
189 +++ new/source/parse.y
190 @@ -884,11 +884,11 @@ static int yylex(void)
191 if (!strcmp(symName, "continue")) return CONTINUE;
192 if (!strcmp(symName, "return")) return RETURN;
193 if (!strcmp(symName, "in")) return IN;
194 if (!strcmp(symName, "$args")) return ARG_LOOKUP;
195 if (!strcmp(symName, "delete") && follow_non_whitespace('(', SYMBOL, DELETE) == DELETE) return DELETE;
196 - if (!strcmp(symName, "define")) return DEFINE;
197 + if (!strcmp(symName, "define") && follow_non_whitespace('(', SYMBOL, DEFINE) == DEFINE) return DEFINE;
198 if (!strcmp(symName, "typeof")) return TYPEOF;
199 if (nextSymIsField) {
200 nextSymIsField = 0;
201 yylval.sym = InstallStringConstSymbol(symName);
202 return FIELD;