Branch data Line data Source code
1 : : /* 2 : : * This file is part of the MicroPython project, http://micropython.org/ 3 : : * 4 : : * The MIT License (MIT) 5 : : * 6 : : * Copyright (c) 2015 Paul Sokolovsky 7 : : * Copyright (c) 2016 Damien P. George 8 : : * Copyright (c) 2021 Jim Mussared 9 : : * 10 : : * Permission is hereby granted, free of charge, to any person obtaining a copy 11 : : * of this software and associated documentation files (the "Software"), to deal 12 : : * in the Software without restriction, including without limitation the rights 13 : : * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 : : * copies of the Software, and to permit persons to whom the Software is 15 : : * furnished to do so, subject to the following conditions: 16 : : * 17 : : * The above copyright notice and this permission notice shall be included in 18 : : * all copies or substantial portions of the Software. 19 : : * 20 : : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 : : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 : : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 : : * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 : : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 : : * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 : : * THE SOFTWARE. 27 : : */ 28 : : 29 : : #include <string.h> 30 : : #include <stdint.h> 31 : : 32 : : #include "py/lexer.h" 33 : : #include "py/frozenmod.h" 34 : : 35 : : #if MICROPY_MODULE_FROZEN 36 : : 37 : : // Null-separated frozen file names. All string-type entries are listed first, 38 : : // followed by mpy-type entries. Use mp_frozen_str_sizes to determine how 39 : : // many string entries. 40 : : extern const char mp_frozen_names[]; 41 : : 42 : : #if MICROPY_MODULE_FROZEN_STR 43 : : 44 : : #ifndef MICROPY_MODULE_FROZEN_LEXER 45 : : #define MICROPY_MODULE_FROZEN_LEXER mp_lexer_new_from_str_len 46 : : #else 47 : : mp_lexer_t *MICROPY_MODULE_FROZEN_LEXER(qstr src_name, const char *str, mp_uint_t len, mp_uint_t free_len); 48 : : #endif 49 : : 50 : : // Size in bytes of each string entry, followed by a zero (terminator). 51 : : extern const uint32_t mp_frozen_str_sizes[]; 52 : : // Null-separated string content. 53 : : extern const char mp_frozen_str_content[]; 54 : : #endif // MICROPY_MODULE_FROZEN_STR 55 : : 56 : : #if MICROPY_MODULE_FROZEN_MPY 57 : : 58 : : #include "py/emitglue.h" 59 : : 60 : : extern const mp_frozen_module_t *const mp_frozen_mpy_content[]; 61 : : 62 : : #endif // MICROPY_MODULE_FROZEN_MPY 63 : : 64 : : // Search for "str" as a frozen entry, returning the stat result 65 : : // (no-exist/file/dir), as well as the type (none/str/mpy) and data. 66 : : // frozen_type can be NULL if its value isn't needed (and then data is assumed to be NULL). 67 : 2796 : mp_import_stat_t mp_find_frozen_module(const char *str, int *frozen_type, void **data) { 68 : 2796 : size_t len = strlen(str); 69 : 2796 : const char *name = mp_frozen_names; 70 : : 71 [ + + ]: 2796 : if (frozen_type != NULL) { 72 : 40 : *frozen_type = MP_FROZEN_NONE; 73 : : } 74 : : 75 : : // Count the number of str lengths we have to find how many str entries. 76 : 2796 : size_t num_str = 0; 77 : : #if MICROPY_MODULE_FROZEN_STR && MICROPY_MODULE_FROZEN_MPY 78 [ + + ]: 11184 : for (const uint32_t *s = mp_frozen_str_sizes; *s != 0; ++s) { 79 : 8388 : ++num_str; 80 : : } 81 : : #endif 82 : : 83 [ + + ]: 35948 : for (size_t i = 0; *name != 0; i++) { 84 : 33240 : size_t entry_len = strlen(name); 85 [ + + + + ]: 33240 : if (entry_len >= len && memcmp(str, name, len) == 0) { 86 : : // Query is a prefix of the current entry. 87 [ + + ]: 124 : if (entry_len == len) { 88 : : // Exact match --> file. 89 : : 90 [ + + ]: 80 : if (frozen_type != NULL) { 91 : : #if MICROPY_MODULE_FROZEN_STR 92 [ + + ]: 40 : if (i < num_str) { 93 : 6 : *frozen_type = MP_FROZEN_STR; 94 : : // Use the size table to figure out where this index starts. 95 : 6 : size_t offset = 0; 96 [ + + ]: 12 : for (size_t j = 0; j < i; ++j) { 97 : 6 : offset += mp_frozen_str_sizes[j] + 1; 98 : : } 99 : 6 : size_t content_len = mp_frozen_str_sizes[i]; 100 : 6 : const char *content = &mp_frozen_str_content[offset]; 101 : : 102 : : // Note: str & len have been updated by find_frozen_entry to strip 103 : : // the ".frozen/" prefix (to avoid this being a distinct qstr to 104 : : // the original path QSTR in frozen_content.c). 105 : 6 : qstr source = qstr_from_strn(str, len); 106 : 6 : mp_lexer_t *lex = MICROPY_MODULE_FROZEN_LEXER(source, content, content_len, 0); 107 : 6 : *data = lex; 108 : : } 109 : : #endif 110 : : 111 : : #if MICROPY_MODULE_FROZEN_MPY 112 [ + + ]: 40 : if (i >= num_str) { 113 : 34 : *frozen_type = MP_FROZEN_MPY; 114 : : // Load the corresponding index as a raw_code, taking 115 : : // into account any string entries to offset by. 116 : 34 : *data = (void *)mp_frozen_mpy_content[i - num_str]; 117 : : } 118 : : #endif 119 : : } 120 : : 121 : 80 : return MP_IMPORT_STAT_FILE; 122 [ + + ]: 44 : } else if (name[len] == '/') { 123 : : // Matches up to directory separator, this is a valid 124 : : // directory path. 125 : : return MP_IMPORT_STAT_DIR; 126 : : } 127 : : } 128 : : // Skip null separator. 129 : 33152 : name += entry_len + 1; 130 : : } 131 : : 132 : : return MP_IMPORT_STAT_NO_EXIST; 133 : : } 134 : : 135 : : #endif // MICROPY_MODULE_FROZEN