1 /*
2  * This file is part of the MicroPython project, http://micropython.org/
3  *
4  * The MIT License (MIT)
5  *
6  * Copyright (c) 2013, 2014 Damien P. George
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to deal
10  * in the Software without restriction, including without limitation the rights
11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  * copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24  * THE SOFTWARE.
25  */
26 
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <stdint.h>
30 #include <string.h>
31 
32 #include "py/compile.h"
33 #include "py/runtime.h"
34 #include "py/repl.h"
35 #include "py/gc.h"
36 #include "py/frozenmod.h"
37 #include "py/mphal.h"
38 #if MICROPY_HW_ENABLE_USB
39 #include "irq.h"
40 #include "usb.h"
41 #endif
42 #include "shared/readline/readline.h"
43 #include "shared/runtime/pyexec.h"
44 #include "genhdr/mpversion.h"
45 
46 pyexec_mode_kind_t pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL;
47 int pyexec_system_exit = 0;
48 
49 #if MICROPY_REPL_INFO
50 STATIC bool repl_display_debugging_info = 0;
51 #endif
52 
53 #define EXEC_FLAG_PRINT_EOF (1)
54 #define EXEC_FLAG_ALLOW_DEBUGGING (2)
55 #define EXEC_FLAG_IS_REPL (4)
56 #define EXEC_FLAG_SOURCE_IS_RAW_CODE (8)
57 #define EXEC_FLAG_SOURCE_IS_VSTR (16)
58 #define EXEC_FLAG_SOURCE_IS_FILENAME (32)
59 #define EXEC_FLAG_SOURCE_IS_READER (64)
60 
61 // parses, compiles and executes the code in the lexer
62 // frees the lexer before returning
63 // EXEC_FLAG_PRINT_EOF prints 2 EOF chars: 1 after normal output, 1 after exception output
64 // EXEC_FLAG_ALLOW_DEBUGGING allows debugging info to be printed after executing the code
65 // EXEC_FLAG_IS_REPL is used for REPL inputs (flag passed on to mp_compile)
parse_compile_execute(const void * source,mp_parse_input_kind_t input_kind,int exec_flags)66 STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input_kind, int exec_flags) {
67     int ret = 0;
68     #if MICROPY_REPL_INFO
69     uint32_t start = 0;
70     #endif
71 
72     #ifdef MICROPY_BOARD_BEFORE_PYTHON_EXEC
73     MICROPY_BOARD_BEFORE_PYTHON_EXEC(input_kind, exec_flags);
74     #endif
75 
76     // by default a SystemExit exception returns 0
77     pyexec_system_exit = 0;
78 
79     nlr_buf_t nlr;
80     nlr.ret_val = NULL;
81     if (nlr_push(&nlr) == 0) {
82         mp_obj_t module_fun;
83         #if MICROPY_MODULE_FROZEN_MPY
84         if (exec_flags & EXEC_FLAG_SOURCE_IS_RAW_CODE) {
85             // source is a raw_code object, create the function
86             module_fun = mp_make_function_from_raw_code(source, MP_OBJ_NULL, MP_OBJ_NULL);
87         } else
88         #endif
89         {
90             #if MICROPY_ENABLE_COMPILER
91             mp_lexer_t *lex;
92             if (exec_flags & EXEC_FLAG_SOURCE_IS_VSTR) {
93                 const vstr_t *vstr = source;
94                 lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr->buf, vstr->len, 0);
95             } else if (exec_flags & EXEC_FLAG_SOURCE_IS_READER) {
96                 lex = mp_lexer_new(MP_QSTR__lt_stdin_gt_, *(mp_reader_t *)source);
97             } else if (exec_flags & EXEC_FLAG_SOURCE_IS_FILENAME) {
98                 lex = mp_lexer_new_from_file(source);
99             } else {
100                 lex = (mp_lexer_t *)source;
101             }
102             // source is a lexer, parse and compile the script
103             qstr source_name = lex->source_name;
104             mp_parse_tree_t parse_tree = mp_parse(lex, input_kind);
105             module_fun = mp_compile(&parse_tree, source_name, exec_flags & EXEC_FLAG_IS_REPL);
106             #else
107             mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("script compilation not supported"));
108             #endif
109         }
110 
111         // execute code
112         mp_hal_set_interrupt_char(CHAR_CTRL_C); // allow ctrl-C to interrupt us
113         #if MICROPY_REPL_INFO
114         start = mp_hal_ticks_ms();
115         #endif
116         mp_call_function_0(module_fun);
117         mp_hal_set_interrupt_char(-1); // disable interrupt
118         mp_handle_pending(true); // handle any pending exceptions (and any callbacks)
119         nlr_pop();
120         ret = 1;
121         if (exec_flags & EXEC_FLAG_PRINT_EOF) {
122             mp_hal_stdout_tx_strn("\x04", 1);
123         }
124     } else {
125         // uncaught exception
126         mp_hal_set_interrupt_char(-1); // disable interrupt
127         mp_handle_pending(false); // clear any pending exceptions (and run any callbacks)
128 
129         if (exec_flags & EXEC_FLAG_SOURCE_IS_READER) {
130             const mp_reader_t *reader = source;
131             reader->close(reader->data);
132         }
133 
134         // print EOF after normal output
135         if (exec_flags & EXEC_FLAG_PRINT_EOF) {
136             mp_hal_stdout_tx_strn("\x04", 1);
137         }
138         // check for SystemExit
139         if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t *)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_SystemExit))) {
140             // at the moment, the value of SystemExit is unused
141             ret = pyexec_system_exit;
142         } else {
143             mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
144             ret = 0;
145         }
146     }
147 
148     #if MICROPY_REPL_INFO
149     // display debugging info if wanted
150     if ((exec_flags & EXEC_FLAG_ALLOW_DEBUGGING) && repl_display_debugging_info) {
151         mp_uint_t ticks = mp_hal_ticks_ms() - start; // TODO implement a function that does this properly
152         printf("took " UINT_FMT " ms\n", ticks);
153         // qstr info
154         {
155             size_t n_pool, n_qstr, n_str_data_bytes, n_total_bytes;
156             qstr_pool_info(&n_pool, &n_qstr, &n_str_data_bytes, &n_total_bytes);
157             printf("qstr:\n  n_pool=%u\n  n_qstr=%u\n  "
158                 "n_str_data_bytes=%u\n  n_total_bytes=%u\n",
159                 (unsigned)n_pool, (unsigned)n_qstr, (unsigned)n_str_data_bytes, (unsigned)n_total_bytes);
160         }
161 
162         #if MICROPY_ENABLE_GC
163         // run collection and print GC info
164         gc_collect();
165         gc_dump_info();
166         #endif
167     }
168     #endif
169 
170     if (exec_flags & EXEC_FLAG_PRINT_EOF) {
171         mp_hal_stdout_tx_strn("\x04", 1);
172     }
173 
174     #ifdef MICROPY_BOARD_AFTER_PYTHON_EXEC
175     MICROPY_BOARD_AFTER_PYTHON_EXEC(input_kind, exec_flags, nlr.ret_val, &ret);
176     #endif
177 
178     return ret;
179 }
180 
181 #if MICROPY_ENABLE_COMPILER
182 
183 // This can be configured by a port (and even configured to a function to be
184 // computed dynamically) to indicate the maximum number of bytes that can be
185 // held in the stdin buffer.
186 #ifndef MICROPY_REPL_STDIN_BUFFER_MAX
187 #define MICROPY_REPL_STDIN_BUFFER_MAX (256)
188 #endif
189 
190 typedef struct _mp_reader_stdin_t {
191     bool eof;
192     uint16_t window_max;
193     uint16_t window_remain;
194 } mp_reader_stdin_t;
195 
mp_reader_stdin_readbyte(void * data)196 STATIC mp_uint_t mp_reader_stdin_readbyte(void *data) {
197     mp_reader_stdin_t *reader = (mp_reader_stdin_t *)data;
198 
199     if (reader->eof) {
200         return MP_READER_EOF;
201     }
202 
203     int c = mp_hal_stdin_rx_chr();
204 
205     if (c == CHAR_CTRL_C || c == CHAR_CTRL_D) {
206         reader->eof = true;
207         mp_hal_stdout_tx_strn("\x04", 1); // indicate end to host
208         if (c == CHAR_CTRL_C) {
209             #if MICROPY_KBD_EXCEPTION
210             MP_STATE_VM(mp_kbd_exception).traceback_data = NULL;
211             nlr_raise(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)));
212             #else
213             mp_raise_type(&mp_type_KeyboardInterrupt);
214             #endif
215         } else {
216             return MP_READER_EOF;
217         }
218     }
219 
220     if (--reader->window_remain == 0) {
221         mp_hal_stdout_tx_strn("\x01", 1); // indicate window available to host
222         reader->window_remain = reader->window_max;
223     }
224 
225     return c;
226 }
227 
mp_reader_stdin_close(void * data)228 STATIC void mp_reader_stdin_close(void *data) {
229     mp_reader_stdin_t *reader = (mp_reader_stdin_t *)data;
230     if (!reader->eof) {
231         reader->eof = true;
232         mp_hal_stdout_tx_strn("\x04", 1); // indicate end to host
233         for (;;) {
234             int c = mp_hal_stdin_rx_chr();
235             if (c == CHAR_CTRL_C || c == CHAR_CTRL_D) {
236                 break;
237             }
238         }
239     }
240 }
241 
mp_reader_new_stdin(mp_reader_t * reader,mp_reader_stdin_t * reader_stdin,uint16_t buf_max)242 STATIC void mp_reader_new_stdin(mp_reader_t *reader, mp_reader_stdin_t *reader_stdin, uint16_t buf_max) {
243     // Make flow-control window half the buffer size, and indicate to the host that 2x windows are
244     // free (sending the window size implicitly indicates that a window is free, and then the 0x01
245     // indicates that another window is free).
246     size_t window = buf_max / 2;
247     char reply[3] = { window & 0xff, window >> 8, 0x01 };
248     mp_hal_stdout_tx_strn(reply, sizeof(reply));
249 
250     reader_stdin->eof = false;
251     reader_stdin->window_max = window;
252     reader_stdin->window_remain = window;
253     reader->data = reader_stdin;
254     reader->readbyte = mp_reader_stdin_readbyte;
255     reader->close = mp_reader_stdin_close;
256 }
257 
do_reader_stdin(int c)258 STATIC int do_reader_stdin(int c) {
259     if (c != 'A') {
260         // Unsupported command.
261         mp_hal_stdout_tx_strn("R\x00", 2);
262         return 0;
263     }
264 
265     // Indicate reception of command.
266     mp_hal_stdout_tx_strn("R\x01", 2);
267 
268     mp_reader_t reader;
269     mp_reader_stdin_t reader_stdin;
270     mp_reader_new_stdin(&reader, &reader_stdin, MICROPY_REPL_STDIN_BUFFER_MAX);
271     int exec_flags = EXEC_FLAG_PRINT_EOF | EXEC_FLAG_SOURCE_IS_READER;
272     return parse_compile_execute(&reader, MP_PARSE_FILE_INPUT, exec_flags);
273 }
274 
275 #if MICROPY_REPL_EVENT_DRIVEN
276 
277 typedef struct _repl_t {
278     // This structure originally also held current REPL line,
279     // but it was moved to MP_STATE_VM(repl_line) as containing
280     // root pointer. Still keep structure in case more state
281     // will be added later.
282     // vstr_t line;
283     bool cont_line;
284     bool paste_mode;
285 } repl_t;
286 
287 repl_t repl;
288 
289 STATIC int pyexec_raw_repl_process_char(int c);
290 STATIC int pyexec_friendly_repl_process_char(int c);
291 
pyexec_event_repl_init(void)292 void pyexec_event_repl_init(void) {
293     MP_STATE_VM(repl_line) = vstr_new(32);
294     repl.cont_line = false;
295     repl.paste_mode = false;
296     // no prompt before printing friendly REPL banner or entering raw REPL
297     readline_init(MP_STATE_VM(repl_line), "");
298     if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
299         pyexec_raw_repl_process_char(CHAR_CTRL_A);
300     } else {
301         pyexec_friendly_repl_process_char(CHAR_CTRL_B);
302     }
303 }
304 
pyexec_raw_repl_process_char(int c)305 STATIC int pyexec_raw_repl_process_char(int c) {
306     if (c == CHAR_CTRL_A) {
307         // reset raw REPL
308         if (vstr_len(MP_STATE_VM(repl_line)) == 2 && vstr_str(MP_STATE_VM(repl_line))[0] == CHAR_CTRL_E) {
309             int ret = do_reader_stdin(vstr_str(MP_STATE_VM(repl_line))[1]);
310             if (ret & PYEXEC_FORCED_EXIT) {
311                 return ret;
312             }
313             goto reset;
314         }
315         mp_hal_stdout_tx_str("raw REPL; CTRL-B to exit\r\n");
316         goto reset;
317     } else if (c == CHAR_CTRL_B) {
318         // change to friendly REPL
319         pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL;
320         vstr_reset(MP_STATE_VM(repl_line));
321         repl.cont_line = false;
322         repl.paste_mode = false;
323         pyexec_friendly_repl_process_char(CHAR_CTRL_B);
324         return 0;
325     } else if (c == CHAR_CTRL_C) {
326         // clear line
327         vstr_reset(MP_STATE_VM(repl_line));
328         return 0;
329     } else if (c == CHAR_CTRL_D) {
330         // input finished
331     } else {
332         // let through any other raw 8-bit value
333         vstr_add_byte(MP_STATE_VM(repl_line), c);
334         return 0;
335     }
336 
337     // indicate reception of command
338     mp_hal_stdout_tx_str("OK");
339 
340     if (MP_STATE_VM(repl_line)->len == 0) {
341         // exit for a soft reset
342         mp_hal_stdout_tx_str("\r\n");
343         vstr_clear(MP_STATE_VM(repl_line));
344         return PYEXEC_FORCED_EXIT;
345     }
346 
347     int ret = parse_compile_execute(MP_STATE_VM(repl_line), MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF | EXEC_FLAG_SOURCE_IS_VSTR);
348     if (ret & PYEXEC_FORCED_EXIT) {
349         return ret;
350     }
351 
352 reset:
353     vstr_reset(MP_STATE_VM(repl_line));
354     mp_hal_stdout_tx_str(">");
355 
356     return 0;
357 }
358 
pyexec_friendly_repl_process_char(int c)359 STATIC int pyexec_friendly_repl_process_char(int c) {
360     if (repl.paste_mode) {
361         if (c == CHAR_CTRL_C) {
362             // cancel everything
363             mp_hal_stdout_tx_str("\r\n");
364             goto input_restart;
365         } else if (c == CHAR_CTRL_D) {
366             // end of input
367             mp_hal_stdout_tx_str("\r\n");
368             int ret = parse_compile_execute(MP_STATE_VM(repl_line), MP_PARSE_FILE_INPUT, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL | EXEC_FLAG_SOURCE_IS_VSTR);
369             if (ret & PYEXEC_FORCED_EXIT) {
370                 return ret;
371             }
372             goto input_restart;
373         } else {
374             // add char to buffer and echo
375             vstr_add_byte(MP_STATE_VM(repl_line), c);
376             if (c == '\r') {
377                 mp_hal_stdout_tx_str("\r\n=== ");
378             } else {
379                 char buf[1] = {c};
380                 mp_hal_stdout_tx_strn(buf, 1);
381             }
382             return 0;
383         }
384     }
385 
386     int ret = readline_process_char(c);
387 
388     if (!repl.cont_line) {
389 
390         if (ret == CHAR_CTRL_A) {
391             // change to raw REPL
392             pyexec_mode_kind = PYEXEC_MODE_RAW_REPL;
393             mp_hal_stdout_tx_str("\r\n");
394             pyexec_raw_repl_process_char(CHAR_CTRL_A);
395             return 0;
396         } else if (ret == CHAR_CTRL_B) {
397             // reset friendly REPL
398             mp_hal_stdout_tx_str("\r\n");
399             mp_hal_stdout_tx_str("MicroPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME "\r\n");
400             #if MICROPY_PY_BUILTINS_HELP
401             mp_hal_stdout_tx_str("Type \"help()\" for more information.\r\n");
402             #endif
403             goto input_restart;
404         } else if (ret == CHAR_CTRL_C) {
405             // break
406             mp_hal_stdout_tx_str("\r\n");
407             goto input_restart;
408         } else if (ret == CHAR_CTRL_D) {
409             // exit for a soft reset
410             mp_hal_stdout_tx_str("\r\n");
411             vstr_clear(MP_STATE_VM(repl_line));
412             return PYEXEC_FORCED_EXIT;
413         } else if (ret == CHAR_CTRL_E) {
414             // paste mode
415             mp_hal_stdout_tx_str("\r\npaste mode; Ctrl-C to cancel, Ctrl-D to finish\r\n=== ");
416             vstr_reset(MP_STATE_VM(repl_line));
417             repl.paste_mode = true;
418             return 0;
419         }
420 
421         if (ret < 0) {
422             return 0;
423         }
424 
425         if (!mp_repl_continue_with_input(vstr_null_terminated_str(MP_STATE_VM(repl_line)))) {
426             goto exec;
427         }
428 
429         vstr_add_byte(MP_STATE_VM(repl_line), '\n');
430         repl.cont_line = true;
431         readline_note_newline("... ");
432         return 0;
433 
434     } else {
435 
436         if (ret == CHAR_CTRL_C) {
437             // cancel everything
438             mp_hal_stdout_tx_str("\r\n");
439             repl.cont_line = false;
440             goto input_restart;
441         } else if (ret == CHAR_CTRL_D) {
442             // stop entering compound statement
443             goto exec;
444         }
445 
446         if (ret < 0) {
447             return 0;
448         }
449 
450         if (mp_repl_continue_with_input(vstr_null_terminated_str(MP_STATE_VM(repl_line)))) {
451             vstr_add_byte(MP_STATE_VM(repl_line), '\n');
452             readline_note_newline("... ");
453             return 0;
454         }
455 
456     exec:;
457         int ret = parse_compile_execute(MP_STATE_VM(repl_line), MP_PARSE_SINGLE_INPUT, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL | EXEC_FLAG_SOURCE_IS_VSTR);
458         if (ret & PYEXEC_FORCED_EXIT) {
459             return ret;
460         }
461 
462     input_restart:
463         vstr_reset(MP_STATE_VM(repl_line));
464         repl.cont_line = false;
465         repl.paste_mode = false;
466         readline_init(MP_STATE_VM(repl_line), ">>> ");
467         return 0;
468     }
469 }
470 
471 uint8_t pyexec_repl_active;
pyexec_event_repl_process_char(int c)472 int pyexec_event_repl_process_char(int c) {
473     pyexec_repl_active = 1;
474     int res;
475     if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
476         res = pyexec_raw_repl_process_char(c);
477     } else {
478         res = pyexec_friendly_repl_process_char(c);
479     }
480     pyexec_repl_active = 0;
481     return res;
482 }
483 
484 #else // MICROPY_REPL_EVENT_DRIVEN
485 
pyexec_raw_repl(void)486 int pyexec_raw_repl(void) {
487     vstr_t line;
488     vstr_init(&line, 32);
489 
490 raw_repl_reset:
491     mp_hal_stdout_tx_str("raw REPL; CTRL-B to exit\r\n");
492 
493     for (;;) {
494         vstr_reset(&line);
495         mp_hal_stdout_tx_str(">");
496         for (;;) {
497             int c = mp_hal_stdin_rx_chr();
498             if (c == CHAR_CTRL_A) {
499                 // reset raw REPL
500                 if (vstr_len(&line) == 2 && vstr_str(&line)[0] == CHAR_CTRL_E) {
501                     int ret = do_reader_stdin(vstr_str(&line)[1]);
502                     if (ret & PYEXEC_FORCED_EXIT) {
503                         return ret;
504                     }
505                     vstr_reset(&line);
506                     mp_hal_stdout_tx_str(">");
507                     continue;
508                 }
509                 goto raw_repl_reset;
510             } else if (c == CHAR_CTRL_B) {
511                 // change to friendly REPL
512                 mp_hal_stdout_tx_str("\r\n");
513                 vstr_clear(&line);
514                 pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL;
515                 return 0;
516             } else if (c == CHAR_CTRL_C) {
517                 // clear line
518                 vstr_reset(&line);
519             } else if (c == CHAR_CTRL_D) {
520                 // input finished
521                 break;
522             } else {
523                 // let through any other raw 8-bit value
524                 vstr_add_byte(&line, c);
525             }
526         }
527 
528         // indicate reception of command
529         mp_hal_stdout_tx_str("OK");
530 
531         if (line.len == 0) {
532             // exit for a soft reset
533             mp_hal_stdout_tx_str("\r\n");
534             vstr_clear(&line);
535             return PYEXEC_FORCED_EXIT;
536         }
537 
538         int ret = parse_compile_execute(&line, MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF | EXEC_FLAG_SOURCE_IS_VSTR);
539         if (ret & PYEXEC_FORCED_EXIT) {
540             return ret;
541         }
542     }
543 }
544 
pyexec_friendly_repl(void)545 int pyexec_friendly_repl(void) {
546     vstr_t line;
547     vstr_init(&line, 32);
548 
549 friendly_repl_reset:
550     mp_hal_stdout_tx_str("MicroPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME "\r\n");
551     #if MICROPY_PY_BUILTINS_HELP
552     mp_hal_stdout_tx_str("Type \"help()\" for more information.\r\n");
553     #endif
554 
555     // to test ctrl-C
556     /*
557     {
558         uint32_t x[4] = {0x424242, 0xdeaddead, 0x242424, 0xdeadbeef};
559         for (;;) {
560             nlr_buf_t nlr;
561             printf("pyexec_repl: %p\n", x);
562             mp_hal_set_interrupt_char(CHAR_CTRL_C);
563             if (nlr_push(&nlr) == 0) {
564                 for (;;) {
565                 }
566             } else {
567                 printf("break\n");
568             }
569         }
570     }
571     */
572 
573     for (;;) {
574     input_restart:
575 
576         #if MICROPY_HW_ENABLE_USB
577         if (usb_vcp_is_enabled()) {
578             // If the user gets to here and interrupts are disabled then
579             // they'll never see the prompt, traceback etc. The USB REPL needs
580             // interrupts to be enabled or no transfers occur. So we try to
581             // do the user a favor and reenable interrupts.
582             if (query_irq() == IRQ_STATE_DISABLED) {
583                 enable_irq(IRQ_STATE_ENABLED);
584                 mp_hal_stdout_tx_str("MPY: enabling IRQs\r\n");
585             }
586         }
587         #endif
588 
589         // If the GC is locked at this point there is no way out except a reset,
590         // so force the GC to be unlocked to help the user debug what went wrong.
591         if (MP_STATE_MEM(gc_lock_depth) != 0) {
592             MP_STATE_MEM(gc_lock_depth) = 0;
593         }
594 
595         vstr_reset(&line);
596         int ret = readline(&line, ">>> ");
597         mp_parse_input_kind_t parse_input_kind = MP_PARSE_SINGLE_INPUT;
598 
599         if (ret == CHAR_CTRL_A) {
600             // change to raw REPL
601             mp_hal_stdout_tx_str("\r\n");
602             vstr_clear(&line);
603             pyexec_mode_kind = PYEXEC_MODE_RAW_REPL;
604             return 0;
605         } else if (ret == CHAR_CTRL_B) {
606             // reset friendly REPL
607             mp_hal_stdout_tx_str("\r\n");
608             goto friendly_repl_reset;
609         } else if (ret == CHAR_CTRL_C) {
610             // break
611             mp_hal_stdout_tx_str("\r\n");
612             continue;
613         } else if (ret == CHAR_CTRL_D) {
614             // exit for a soft reset
615             mp_hal_stdout_tx_str("\r\n");
616             vstr_clear(&line);
617             return PYEXEC_FORCED_EXIT;
618         } else if (ret == CHAR_CTRL_E) {
619             // paste mode
620             mp_hal_stdout_tx_str("\r\npaste mode; Ctrl-C to cancel, Ctrl-D to finish\r\n=== ");
621             vstr_reset(&line);
622             for (;;) {
623                 char c = mp_hal_stdin_rx_chr();
624                 if (c == CHAR_CTRL_C) {
625                     // cancel everything
626                     mp_hal_stdout_tx_str("\r\n");
627                     goto input_restart;
628                 } else if (c == CHAR_CTRL_D) {
629                     // end of input
630                     mp_hal_stdout_tx_str("\r\n");
631                     break;
632                 } else {
633                     // add char to buffer and echo
634                     vstr_add_byte(&line, c);
635                     if (c == '\r') {
636                         mp_hal_stdout_tx_str("\r\n=== ");
637                     } else {
638                         mp_hal_stdout_tx_strn(&c, 1);
639                     }
640                 }
641             }
642             parse_input_kind = MP_PARSE_FILE_INPUT;
643         } else if (vstr_len(&line) == 0) {
644             continue;
645         } else {
646             // got a line with non-zero length, see if it needs continuing
647             while (mp_repl_continue_with_input(vstr_null_terminated_str(&line))) {
648                 vstr_add_byte(&line, '\n');
649                 ret = readline(&line, "... ");
650                 if (ret == CHAR_CTRL_C) {
651                     // cancel everything
652                     mp_hal_stdout_tx_str("\r\n");
653                     goto input_restart;
654                 } else if (ret == CHAR_CTRL_D) {
655                     // stop entering compound statement
656                     break;
657                 }
658             }
659         }
660 
661         ret = parse_compile_execute(&line, parse_input_kind, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL | EXEC_FLAG_SOURCE_IS_VSTR);
662         if (ret & PYEXEC_FORCED_EXIT) {
663             return ret;
664         }
665     }
666 }
667 
668 #endif // MICROPY_REPL_EVENT_DRIVEN
669 #endif // MICROPY_ENABLE_COMPILER
670 
pyexec_file(const char * filename)671 int pyexec_file(const char *filename) {
672     return parse_compile_execute(filename, MP_PARSE_FILE_INPUT, EXEC_FLAG_SOURCE_IS_FILENAME);
673 }
674 
pyexec_file_if_exists(const char * filename)675 int pyexec_file_if_exists(const char *filename) {
676     #if MICROPY_MODULE_FROZEN
677     if (mp_frozen_stat(filename) == MP_IMPORT_STAT_FILE) {
678         return pyexec_frozen_module(filename);
679     }
680     #endif
681     if (mp_import_stat(filename) != MP_IMPORT_STAT_FILE) {
682         return 1; // success (no file is the same as an empty file executing without fail)
683     }
684     return pyexec_file(filename);
685 }
686 
687 #if MICROPY_MODULE_FROZEN
pyexec_frozen_module(const char * name)688 int pyexec_frozen_module(const char *name) {
689     void *frozen_data;
690     int frozen_type = mp_find_frozen_module(name, strlen(name), &frozen_data);
691 
692     switch (frozen_type) {
693         #if MICROPY_MODULE_FROZEN_STR
694         case MP_FROZEN_STR:
695             return parse_compile_execute(frozen_data, MP_PARSE_FILE_INPUT, 0);
696         #endif
697 
698         #if MICROPY_MODULE_FROZEN_MPY
699         case MP_FROZEN_MPY:
700             return parse_compile_execute(frozen_data, MP_PARSE_FILE_INPUT, EXEC_FLAG_SOURCE_IS_RAW_CODE);
701         #endif
702 
703         default:
704             printf("could not find module '%s'\n", name);
705             return false;
706     }
707 }
708 #endif
709 
710 #if MICROPY_REPL_INFO
pyb_set_repl_info(mp_obj_t o_value)711 mp_obj_t pyb_set_repl_info(mp_obj_t o_value) {
712     repl_display_debugging_info = mp_obj_get_int(o_value);
713     return mp_const_none;
714 }
715 MP_DEFINE_CONST_FUN_OBJ_1(pyb_set_repl_info_obj, pyb_set_repl_info);
716 #endif
717