re-fresh
[nedit-bw.git] / switch-statement.patch
blobd236ce145a8e3b390b850a7408ac8296a71a1322
1 ---
3 source/highlightData.c | 2
4 source/parse.y | 203 ++++++++++++++++++++++++++++++++++++++++++++++++-
5 2 files changed, 203 insertions(+), 2 deletions(-)
7 diff --quilt old/source/highlightData.c new/source/highlightData.c
8 --- old/source/highlightData.c
9 +++ new/source/highlightData.c
10 @@ -558,7 +558,7 @@ static char *DefaultPatternSets[] = {
11 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\
12 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|select_word|deselect-all|deselect_all|focusIn|focusOut|process-return|process_return|process-tab|process_tab|insert-string|insert_string|mouse_pan)(?=\\s*\\()\":::Subroutine::\n\
13 Macro Hooks:\"<(?:(?:pre|post)_(?:open|save)|cursor_moved|modified|(?:losing_)?focus|language_mode)_hook(?=\\s*\\()\":::Subroutine1::\n\
14 - Keyword:\"<(?:break|continue|define|delete|do|else|finally|for|if|in|readonly|return|typeof|while)>\":::Keyword::\n\
15 + Keyword:\"<(?:break|case|continue|default|define|delete|do|else|finally|for|if|in|readonly|return|switch|typeof|while)>\":::Keyword::\n\
16 Braces:\"[{}\\[\\]()<>,.:;~!&|^%*/?=+-]\":::Keyword::\n\
17 Global Variable:\"\\$[A-Za-z0-9_]+\":::Identifier1::\n\
18 String sq:\"'\":\"'\"::String::\n\
19 diff --quilt old/source/parse.y new/source/parse.y
20 --- old/source/parse.y
21 +++ new/source/parse.y
22 @@ -109,6 +109,61 @@ static int nextSymIsField = 0;
23 /* set to 1 when we don't want a full symbol, just a name (string) for a
24 field name following a '.' */
26 +#define PTRBLK_SIZE ((64 - sizeof(void *)) / sizeof(void *))
27 +typedef struct PtrBlkTag {
28 + void *ptrs[PTRBLK_SIZE];
29 + struct PtrBlkTag *next;
30 +} PtrBlk;
31 +typedef struct PtrListTag {
32 + PtrBlk *head, *tail;
33 + int nPtrs;
34 +} PtrList;
36 +#define PTRBLK_START(tgt) \
37 + do { \
38 + (tgt).head = (tgt).tail = NULL; \
39 + (tgt).nPtrs = 0; \
40 + } while (0)
42 +#define PTRBLK_CPY(tgt, src) \
43 + do { \
44 + (tgt).head = (src).head; \
45 + (tgt).tail = (src).tail; \
46 + (tgt).nPtrs = (src).nPtrs; \
47 + } while (0)
49 +#define PTRBLK_ADD(tgt, ptr) \
50 + do { \
51 + if ((tgt).nPtrs % PTRBLK_SIZE == 0) { \
52 + PtrBlk *ptrblk = malloc(sizeof(*ptrblk)); \
53 + ptrblk->next = NULL; \
54 + if ((tgt).head == NULL) { \
55 + (tgt).head = (tgt).tail = ptrblk; \
56 + } \
57 + else {\
58 + (tgt).tail->next = ptrblk; \
59 + (tgt).tail = ptrblk; \
60 + } \
61 + } \
62 + (tgt).tail->ptrs[(tgt).nPtrs % PTRBLK_SIZE] = (ptr); \
63 + (tgt).nPtrs++; \
64 + } while (0)
66 +#define PTRBLK_FORALL(src, ...) \
67 + do { \
68 + int i = 0; \
69 + while (i < (src).nPtrs) { \
70 + void *ptr = (src).head->ptrs[i % PTRBLK_SIZE]; \
71 + (__VA_ARGS__); \
72 + i++; \
73 + if (i % PTRBLK_SIZE == 0 || i == (src).nPtrs) { \
74 + PtrBlk *next = (src).head->next; \
75 + free((src).head); \
76 + (src).head = next; \
77 + } \
78 + } \
79 + } while (0)
83 %union {
84 @@ -117,12 +172,21 @@ static int nextSymIsField = 0;
85 const char *str;
86 enum operations oper;
87 AccumulatorData *acc;
88 + struct {
89 + unsigned hasDefault:1;
90 + PtrList plist;
91 + Inst *start;
92 + } swstmts;
93 + struct {
94 + unsigned isDefault:1;
95 + Inst *branch;
96 + } swlabel;
98 %token <str> SYMBOL STRING FIELD
99 %token <num> NUMBER
100 %token DELETE ARG_LOOKUP
101 %token IF WHILE DO ELSE FOR BREAK CONTINUE RETURN DEFINE TYPEOF KEYVAL READONLY
102 -%token FINALLY
103 +%token FINALLY SWITCH CASE DEFAULT
104 %type <num> keyargs key keyopt catlist fnarglsopt fnarglist fnarg
105 %type <inst> cond branch for while do else and or mark
106 %type <str> evalsym
107 @@ -134,6 +198,9 @@ static int nextSymIsField = 0;
108 %type <inst> lventry
109 %token ARGSEP
110 %type <inst> thenx elsex thenelsex
111 +%type <inst> switch switchcont
112 +%type <swstmts> swstmts
113 +%type <swlabel> swlabel
115 %nonassoc IF_NO_ELSE
116 %nonassoc ELSE
117 @@ -266,6 +333,49 @@ stmt: ';' blank
118 ADD_OP(OP_FINALIZE_LOOP);
121 + | switch '(' switchcont numexpr ')' '{' blank swstmts '}' blank {
122 + int i = 0;
123 + ptrdiff_t offset = 0;
125 + /* do we need a default label to skip all stats? */
126 + if (!$8.hasDefault) {
127 + Inst *branch, *mark = GetPC();
128 + /* we will move the default label by this number back */
129 + ptrdiff_t stmtsLen = mark - $8.start;
131 + /* this is a default: label */
132 + ADD_OP(OP_BRANCH);
133 + branch = GetPC(); ADD_BR_OFF(0);
134 + SET_BR_OFF(branch, GetPC() + stmtsLen);
136 + SwapCode($8.start, mark, GetPC());
137 + offset = 2;
140 + /* simulated break statement */
141 + ADD_OP(OP_PUSH_IMMED); ADD_IMMED(0);
142 + /* fill startLoop with endLoop addr */
143 + SET_BR_OFF($1, GetPC());
144 + /* continue is pop before numexpr */
145 + ADD_OP(OP_END_LOOP); ADD_BR_OFF($3);
146 + /* empty finally block */
147 + ADD_OP(OP_PEEK_POP); ADD_IMMED(2);
148 + ADD_OP(OP_FINALIZE_LOOP);
150 + /* clear swstmts plist */
151 + while (i < $8.plist.nPtrs) {
152 + Inst *br = $8.plist.head->ptrs[i % PTRBLK_SIZE];
153 + br->val.branch += offset;
154 + i++;
155 + if (i % PTRBLK_SIZE == 0 || i == $8.plist.nPtrs) {
156 + PtrBlk *next = $8.plist.head->next;
157 + free($8.plist.head);
158 + $8.plist.head = next;
164 | BREAK numexpropt stmtend blank {
165 ADD_OP(OP_BREAK_LOOP);
167 @@ -744,6 +854,8 @@ do: DO blank { START_LOOP($$); }
169 for: FOR blank { START_LOOP($$); }
171 +switch: SWITCH blank { START_LOOP($$); }
173 else: ELSE blank {
174 ADD_OP(OP_BRANCH); $$ = GetPC(); ADD_BR_OFF(0);
176 @@ -788,6 +900,80 @@ thenelsex: TE {
180 +dup: /* empty */ {
181 + ADD_OP(OP_DUP);
185 +swlabel: CASE dup numexpr ':' blank {
186 + ADD_OP(OP_EQ);
187 + ADD_OP(OP_BRANCH_TRUE);
188 + $$.branch = GetPC(); ADD_BR_OFF(0);
189 + $$.isDefault = 0;
191 + | DEFAULT ':' blank {
192 + ADD_OP(OP_BRANCH);
193 + $$.branch = GetPC(); ADD_BR_OFF(0);
194 + $$.isDefault = 1;
198 +swstmts: swlabel {
199 + $$.start = GetPC();
200 + PTRBLK_START($$.plist);
201 + PTRBLK_ADD($$.plist, $1.branch);
202 + SET_BR_OFF($1.branch, GetPC());
203 + $$.hasDefault = $1.isDefault;
205 + | block {
206 + PTRBLK_START($$.plist);
207 + $$.hasDefault = 0;
209 + | swstmts mark swlabel {
210 + int i;
211 + /* we will move this switch label by this number back */
212 + ptrdiff_t stmtsLen = $2 - $1.start;
213 + /* we will move all previous stmts by this number forth */
214 + ptrdiff_t labelLen = GetPC() - $2;
215 + PtrBlk *curr;
217 + if ($1.hasDefault && $3.isDefault) {
218 + yyerror("multiple default labels in one switch");
219 + YYERROR;
221 + $$.hasDefault = $1.hasDefault || $3.isDefault;
222 + $$.plist = $1.plist;
224 + /*
225 + * the branch target will move forth, but we also add
226 + * the offsets to all labels, so remove it here first
227 + * to eliminating this
228 + */
229 + SET_BR_OFF($3.branch, GetPC() + stmtsLen - labelLen);
230 + /* the branch addr will move back by stmtsLen */
231 + PTRBLK_ADD($$.plist, $3.branch - stmtsLen);
233 + /* move new label in-front of all previous stmts */
234 + $$.start = SwapCode($1.start, $2, GetPC());
236 + /* add the offset to all previous labels */
237 + i = 0;
238 + curr = $$.plist.head;
239 + while (i < $$.plist.nPtrs) {
240 + Inst *br = curr->ptrs[i++ % PTRBLK_SIZE];
241 + if (i % PTRBLK_SIZE == 0) {
242 + curr = curr->next;
244 + br->val.branch += labelLen;
247 + | swstmts block {
248 + $$.hasDefault = $1.hasDefault;
249 + $$.plist = $1.plist;
250 + $$.start = $1.start;
254 dot: '.' %prec '.' {
255 nextSymIsField = 1;
257 @@ -799,6 +985,18 @@ branch: /* nothing */ {
258 ADD_BR_OFF(0);
262 +** for continuing a switch, we need to pop the first expression from the stack,
263 +** but not for the first one, value is the continue address
265 +switchcont: /* nothing */ {
266 + ADD_OP(OP_BRANCH);
267 + ADD_BR_OFF(0);
268 + $$ = GetPC();
269 + ADD_OP(OP_POP);
270 + SET_BR_OFF($$ - 1, GetPC());
273 blank: /* nothing */
274 | blank '\n'
276 @@ -941,6 +1139,9 @@ static int yylex(void)
277 if (!strcmp(symName, "typeof")) return TYPEOF;
278 if (!strcmp(symName, "readonly")) return READONLY;
279 if (!strcmp(symName, "finally")) return FINALLY;
280 + if (!strcmp(symName, "switch")) return SWITCH;
281 + if (!strcmp(symName, "case")) return CASE;
282 + if (!strcmp(symName, "default")) return DEFAULT;
284 yylval.str = LookupString(symName, True);
285 if (nextSymIsField) {