fix hex regex in SH
[nedit-bw.git] / define_macro.patch
bloba088405a9ae1be278e202640dfbbf7500dc19efb
1 ---
3 doc/help.etx | 5 +
4 source/highlightData.c | 2
5 source/macro.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++++-
6 source/parse.y | 2
7 4 files changed, 134 insertions(+), 3 deletions(-)
9 diff --quilt old/source/macro.c new/source/macro.c
10 --- old/source/macro.c
11 +++ new/source/macro.c
12 @@ -430,10 +430,13 @@ static int dictsaveMS(WindowInfo *window
13 static int dictappendMS(WindowInfo *window, DataValue *argList, int nArgs,
14 DataValue *result, char **errMsg);
15 static int dictiselementMS(WindowInfo *window, DataValue *argList, int nArgs,
16 DataValue *result, char **errMsg);
18 +static int defineMS(WindowInfo *window, DataValue *argList, int nArgs,
19 + DataValue *result, char **errMsg);
21 /* Built-in subroutines and variables for the macro language */
22 static const BuiltInSubrName MacroSubrs[] = {
23 { "length", lengthMS },
24 { "get_range", getRangeMS },
25 { "t_print", tPrintMS },
26 @@ -496,10 +499,11 @@ static const BuiltInSubrName MacroSubrs[
27 { "dict_insert", dictinsertMS },
28 { "dict_complete", dictcompleteMS },
29 { "dict_save", dictsaveMS },
30 { "dict_append", dictappendMS },
31 { "dict_is_element", dictiselementMS },
32 + { "define", defineMS },
33 { NULL, NULL } /* sentinel */
36 static const BuiltInSubrName SpecialVars[] = {
37 { "$cursor", cursorMV },
38 @@ -964,13 +968,28 @@ static int readCheckMacroString(Widget d
39 Symbol *sym;
40 DataValue subrPtr;
41 Stack* progStack = (Stack*) XtMalloc(sizeof(Stack));
42 progStack->top = NULL;
43 progStack->size = 0;
44 + regexp *defineRE = NULL;
45 + char *defineMsg;
46 + Boolean defineFound;
48 + /* compile the "define" regex, don't honor "define\nfunction_name" */
49 + defineRE = CompileRE("<define(?=\\s+(?!\\())", &defineMsg,
50 + REDFLT_STANDARD);
51 + /* should only fail if out of mem */
52 + if (NULL == defineRE)
53 + return False;
55 inPtr = string;
57 + defineFound = ExecRE(defineRE, inPtr, NULL, False,
58 + '\0', '\0', NULL, NULL, NULL);
60 while (*inPtr != '\0') {
61 + Boolean haveDefine = False;
63 /* skip over white space and comments */
64 while (*inPtr==' ' || *inPtr=='\t' || *inPtr=='\n'|| *inPtr=='#') {
65 if (*inPtr == '#')
66 while (*inPtr != '\n' && *inPtr != '\0') inPtr++;
67 @@ -978,33 +997,42 @@ static int readCheckMacroString(Widget d
68 inPtr++;
70 if (*inPtr == '\0')
71 break;
73 + /* the current "define" location was parsed inside a ParseMacro() */
74 + if (defineFound && inPtr > defineRE->startp[0]) {
75 + defineFound = ExecRE(defineRE, inPtr, NULL, False,
76 + '\0', '\0', NULL, NULL, NULL);
77 + }
79 /* look for define keyword, and compile and store defined routines */
80 - if (!strncmp(inPtr, "define", 6) && (inPtr[6]==' ' || inPtr[6]=='\t')) {
81 + if (defineFound && defineRE->startp[0] == inPtr) {
82 inPtr += 6;
83 inPtr += strspn(inPtr, " \t\n");
84 namePtr = subrName;
85 while ((namePtr < &subrName[MAX_SYM_LEN - 1])
86 && (isalnum((unsigned char)*inPtr) || *inPtr == '_')) {
87 *namePtr++ = *inPtr++;
89 *namePtr = '\0';
90 if (isalnum((unsigned char)*inPtr) || *inPtr == '_') {
91 + free(defineRE);
92 return ParseError(dialogParent, string, inPtr, errIn,
93 "subroutine name too long");
95 inPtr += strspn(inPtr, " \t\n");
96 if (*inPtr != '{') {
97 if (errPos != NULL) *errPos = stoppedAt;
98 + free(defineRE);
99 return ParseError(dialogParent, string, inPtr,
100 errIn, "expected '{'");
102 prog = ParseMacro(inPtr, &errMsg, &stoppedAt, subrName);
103 if (prog == NULL) {
104 if (errPos != NULL) *errPos = stoppedAt;
105 + free(defineRE);
106 return ParseError(dialogParent, string, stoppedAt,
107 errIn, errMsg);
109 if (runWindow != NULL) {
110 sym = LookupSymbol(subrName);
111 @@ -1020,10 +1048,14 @@ static int readCheckMacroString(Widget d
112 sym->value.val.prog = prog;
115 inPtr = stoppedAt;
117 + /* search for the next "define" */
118 + defineFound = ExecRE(defineRE, inPtr, NULL, False,
119 + '\0', '\0', NULL, NULL, NULL);
121 /* Parse and execute immediate (outside of any define) macro commands
122 and WAIT for them to finish executing before proceeding. Note that
123 the code below is not perfect. If you interleave code blocks with
124 definitions in a file which is loaded from another macro file, it
125 will probably run the code blocks in reverse order! */
126 @@ -1032,10 +1064,11 @@ static int readCheckMacroString(Widget d
127 if (prog == NULL) {
128 if (errPos != NULL) {
129 *errPos = stoppedAt;
132 + free(defineRE);
133 return ParseError(dialogParent, string, stoppedAt,
134 errIn, errMsg);
137 if (runWindow != NULL) {
138 @@ -1071,10 +1104,12 @@ static int readCheckMacroString(Widget d
141 /* This stack is empty, so just free it without checking the members. */
142 XtFree((char*) progStack);
144 + free(defineRE);
146 return True;
150 ** Run a pre-compiled macro, changing the interface state to reflect that
151 @@ -3704,10 +3739,101 @@ static int callMS(WindowInfo *window, Da
152 return False;
154 return OverlayRoutineFromSymbol(sym, nArgs, 1);
158 + * define(func_name, func_body[, "override"])
159 + */
160 +static int defineMS(WindowInfo *window, DataValue *argList, int nArgs,
161 + DataValue *result, char **errMsg)
163 + char stringStorage[3][TYPE_INT_STR_SIZE(int)];
164 + char *name = NULL;
165 + char *body = NULL;
166 + char *bodysave = NULL;
167 + char *stoppedAt = NULL;
168 + char *namePtr;
169 + char *override = NULL;
170 + Program *prog;
171 + Symbol *sym;
172 + DataValue subrPtr;
174 + if (nArgs < 2 || nArgs > 3) {
175 + return wrongNArgsErr(errMsg);
177 + if (!readStringArg(argList[0], &name, stringStorage[0], errMsg)) {
178 + return False;
180 + if (!readStringArg(argList[1], &body, stringStorage[1], errMsg)) {
181 + return False;
183 + if (nArgs > 2) {
184 + if (!readStringArg(argList[2], &override, stringStorage[2], errMsg)) {
185 + return False;
187 + if (strcmp(override, "override")) {
188 + *errMsg = "Unknown parameter for subroutine %s";
189 + return False;
193 + /* check function name */
194 + if (strlen(name) >= MAX_SYM_LEN) {
195 + *errMsg = "subroutine name too long";
196 + return False;
198 + namePtr = name;
199 + while (isalnum((unsigned char)*namePtr) || *namePtr == '_')
200 + namePtr++;
201 + if (*namePtr) {
202 + *errMsg = "subroutine name is not a valid identifier";
203 + return False;
206 + /* add a terminating newline (which command line users are likely to
207 + omit since they are typically invoking a single routine) */
208 + bodysave = XtMalloc(strlen(body) + 2);
209 + if (!bodysave) {
210 + *errMsg = "Internal error";
211 + return False;
213 + strcpy(bodysave, body);
214 + strcat(bodysave, "\n");
216 + /* Parse the macro and report errors if it fails */
217 + prog = ParseMacro(bodysave, errMsg, &stoppedAt, name);
218 + if (!prog) {
219 + ParseError(window->macroCmdData ? window->shell : NULL,
220 + bodysave, stoppedAt, name, *errMsg);
221 + XtFree(bodysave);
222 + return False;
224 + XtFree(bodysave);
226 + sym = LookupSymbol(name);
227 + if (sym) {
228 + if (!override) {
229 + *errMsg = "Try to override existing function.";
230 + return False;
231 + } else {
232 + if (sym->type != MACRO_FUNCTION_SYM) {
233 + *errMsg = "Try to override a non macro function.";
234 + return False;
236 + FreeProgram(sym->value.val.prog);
237 + sym->value.val.prog = prog;
239 + } else {
240 + subrPtr.val.prog = prog;
241 + subrPtr.tag = NO_TAG;
242 + sym = InstallSymbol(name, MACRO_FUNCTION_SYM, subrPtr);
245 + return True;
248 /* T Balinski */
249 static int listDialogMS(WindowInfo *window, DataValue *argList, int nArgs,
250 DataValue *result, char **errMsg)
252 macroCmdInfo *cmdData;
253 diff --quilt old/source/highlightData.c new/source/highlightData.c
254 --- old/source/highlightData.c
255 +++ new/source/highlightData.c
256 @@ -549,11 +549,11 @@ static char *DefaultPatternSets[] = {
257 README:\"NEdit Macro syntax highlighting patterns, version 2.6, maintainer Thorsten Haude, nedit at thorstenhau.de\":::Flag::D\n\
258 Comment:\"#\":\"$\"::Comment::\n\
259 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\
260 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\
261 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\
262 - 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_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|get_matching|set_transient|shell_command|split|string_compare|string_dialog|string_to_clipboard|substring|t_print|tolower|toupper|valid_number|write_file)(?=\\s*\\()\":::Subroutine::\n\
263 + 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_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|get_matching|set_transient|shell_command|split|string_compare|string_dialog|string_to_clipboard|substring|t_print|tolower|toupper|valid_number|write_file)(?=\\s*\\()\":::Subroutine::\n\
264 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\
265 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\
266 Macro Hooks:\"<(?:post_open|pre_open|post_save|cursor_moved|modified|focus|losing_focus)_hook(?=\\s*\\()\":::Subroutine1::\n\
267 Keyword:\"<(?:break|continue|define|delete|else|for|if|in|return|typeof|while)>\":::Keyword::\n\
268 Braces:\"[{}\\[\\]]\":::Keyword::\n\
269 diff --quilt old/doc/help.etx new/doc/help.etx
270 --- old/doc/help.etx
271 +++ new/doc/help.etx
272 @@ -2670,10 +2670,15 @@ Macro Subroutines
274 **clipboard_to_string()**
275 Returns the contents of the clipboard as a macro string. Returns empty
276 string on error.
278 +**define( name, body [, "override"] )**
279 + Defines a new function with name ~name~ and the macro code in ~body~.
280 + If the ~"override"~ option is given the new symbol overrides previously
281 + defined functions.
283 **dialog( message, btn_1_label, btn_2_label, ... )**
284 Pop up a dialog for querying and presenting information to the user. First
285 argument is a string to show in the message area of the dialog.
286 Additional optional arguments represent labels for buttons to appear along
287 the bottom of the dialog. Returns the number of the button pressed (the
288 diff --quilt old/source/parse.y new/source/parse.y
289 --- old/source/parse.y
290 +++ new/source/parse.y
291 @@ -795,11 +795,11 @@ static int yylex(void)
292 if (!strcmp(symName, "continue")) return CONTINUE;
293 if (!strcmp(symName, "return")) return RETURN;
294 if (!strcmp(symName, "in")) return IN;
295 if (!strcmp(symName, "$args")) return ARG_LOOKUP;
296 if (!strcmp(symName, "delete") && follow_non_whitespace('(', SYMBOL, DELETE) == DELETE) return DELETE;
297 - if (!strcmp(symName, "define")) {
298 + if (!strcmp(symName, "define") && follow_non_whitespace('(', SYMBOL, 0) == 0) {
299 InPtr -= 6;
300 return 0;
302 if (!strcmp(symName, "typeof")) return TYPEOF;
303 if (nextSymIsField) {