|
5 | 5 | *
|
6 | 6 | * Copyright (c) 2015 Paul Sokolovsky
|
7 | 7 | * Copyright (c) 2016 Damien P. George
|
| 8 | + * Copyright (c) 2021 Jim Mussared |
8 | 9 | *
|
9 | 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
10 | 11 | * of this software and associated documentation files (the "Software"), to deal
|
|
31 | 32 | #include "py/lexer.h"
|
32 | 33 | #include "py/frozenmod.h"
|
33 | 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 | + |
34 | 42 | #if MICROPY_MODULE_FROZEN_STR
|
35 | 43 |
|
36 | 44 | #ifndef MICROPY_MODULE_FROZEN_LEXER
|
|
39 | 47 | mp_lexer_t *MICROPY_MODULE_FROZEN_LEXER(qstr src_name, const char *str, mp_uint_t len, mp_uint_t free_len);
|
40 | 48 | #endif
|
41 | 49 |
|
42 |
| -extern const char mp_frozen_str_names[]; |
| 50 | +// Size in bytes of each string entry, followed by a zero (terminator). |
43 | 51 | extern const uint32_t mp_frozen_str_sizes[];
|
| 52 | +// Null-separated string content. |
44 | 53 | extern const char mp_frozen_str_content[];
|
45 |
| - |
46 |
| -// On input, *len contains size of name, on output - size of content |
47 |
| -const char *mp_find_frozen_str(const char *str, size_t *len) { |
48 |
| - const char *name = mp_frozen_str_names; |
49 |
| - |
50 |
| - size_t offset = 0; |
51 |
| - for (int i = 0; *name != 0; i++) { |
52 |
| - size_t l = strlen(name); |
53 |
| - if (l == *len && !memcmp(str, name, l)) { |
54 |
| - *len = mp_frozen_str_sizes[i]; |
55 |
| - return mp_frozen_str_content + offset; |
56 |
| - } |
57 |
| - name += l + 1; |
58 |
| - offset += mp_frozen_str_sizes[i] + 1; |
59 |
| - } |
60 |
| - return NULL; |
61 |
| -} |
62 |
| - |
63 |
| -STATIC mp_lexer_t *mp_lexer_frozen_str(const char *str, size_t len) { |
64 |
| - size_t name_len = len; |
65 |
| - const char *content = mp_find_frozen_str(str, &len); |
66 |
| - |
67 |
| - if (content == NULL) { |
68 |
| - return NULL; |
69 |
| - } |
70 |
| - |
71 |
| - qstr source = qstr_from_strn(str, name_len); |
72 |
| - mp_lexer_t *lex = MICROPY_MODULE_FROZEN_LEXER(source, content, len, 0); |
73 |
| - return lex; |
74 |
| -} |
75 |
| - |
76 |
| -#endif |
| 54 | +#endif // MICROPY_MODULE_FROZEN_STR |
77 | 55 |
|
78 | 56 | #if MICROPY_MODULE_FROZEN_MPY
|
79 | 57 |
|
80 | 58 | #include "py/emitglue.h"
|
81 | 59 |
|
82 |
| -extern const
6D4E
char mp_frozen_mpy_names[]; |
83 | 60 | extern const mp_raw_code_t *const mp_frozen_mpy_content[];
|
84 | 61 |
|
85 |
| -STATIC const mp_raw_code_t *mp_find_frozen_mpy(const char *str, size_t len) { |
86 |
| - const char *name = mp_frozen_mpy_names; |
87 |
| - for (size_t i = 0; *name != 0; i++) { |
88 |
| - size_t l = strlen(name); |
89 |
| - if (l == len && !memcmp(str, name, l)) { |
90 |
| - return mp_frozen_mpy_content[i]; |
91 |
| - } |
92 |
| - name += l + 1; |
93 |
| - } |
94 |
| - return NULL; |
95 |
| -} |
| 62 | +#endif // MICROPY_MODULE_FROZEN_MPY |
96 | 63 |
|
97 |
| -#endif |
| 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 | +mp_import_stat_t mp_find_frozen_module(const char *str, int *frozen_type, void **data) { |
| 68 | + size_t len = strlen(str); |
| 69 | + const char *name = mp_frozen_names; |
98 | 70 |
|
99 |
| -#if MICROPY_MODULE_FROZEN |
| 71 | + if (frozen_type != NULL) { |
| 72 | + *frozen_type = MP_FROZEN_NONE; |
| 73 | + } |
100 | 74 |
|
101 |
| -STATIC mp_import_stat_t mp_frozen_stat_helper(const char *name, const char *str) { |
102 |
| - size_t len = strlen(str); |
| 75 | + // Count the number of str lengths we have to find how many str entries. |
| 76 | + size_t num_str = 0; |
| 77 | + #if MICROPY_MODULE_FROZEN_STR && MICROPY_MODULE_FROZEN_MPY |
| 78 | + for (const uint32_t *s = mp_frozen_str_sizes; *s != 0; ++s) { |
| 79 | + ++num_str; |
| 80 | + } |
| 81 | + #endif |
| 82 | + |
| 83 | + for (size_t i = 0; *name != 0; i++) { |
| 84 | + size_t entry_len = strlen(name); |
| 85 | + if (entry_len >= len && memcmp(str, name, len) == 0) { |
| 86 | + // Query is a prefix of the current entry. |
| 87 | + if (entry_len == len) { |
| 88 | + // Exact match --> file. |
| 89 | + |
| 90 | + if (frozen_type != NULL) { |
| 91 | + #if MICROPY_MODULE_FROZEN_STR |
| 92 | + if (i < num_str) { |
| 93 | + *frozen_type = MP_FROZEN_STR; |
| 94 | + // Use the size table to figure out where this index starts. |
| 95 | + size_t offset = 0; |
| 96 | + for (size_t j = 0; j < i; ++j) { |
| 97 | + offset += mp_frozen_str_sizes[j] + 1; |
| 98 | + } |
| 99 | + size_t content_len = mp_frozen_str_sizes[i]; |
| 100 | + 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 | + qstr source = qstr_from_strn(str, len); |
| 106 | + mp_lexer_t *lex = MICROPY_MODULE_FROZEN_LEXER(source, content, content_len, 0); |
| 107 | + *data = lex; |
| 108 | + } |
| 109 | + #endif |
| 110 | + |
| 111 | + #if MICROPY_MODULE_FROZEN_MPY |
| 112 | + if (i >= num_str) { |
| 113 | + *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 | + *data = (void *)mp_frozen_mpy_content[i - num_str]; |
| 117 | + } |
| 118 | + #endif |
| 119 | + } |
103 | 120 |
|
104 |
| - for (int i = 0; *name != 0; i++) { |
105 |
| - size_t l = strlen(name); |
106 |
| - if (l >= len && !memcmp(str, name, len)) { |
107 |
| - if (name[len] == 0) { |
108 | 121 | return MP_IMPORT_STAT_FILE;
|
109 | 122 | } else if (name[len] == '/') {
|
| 123 | + // Matches up to directory separator, this is a valid |
| 124 | + // directory path. |
110 | 125 | return MP_IMPORT_STAT_DIR;
|
111 | 126 | }
|
112 | 127 | }
|
113 |
| - name += l + 1; |
114 |
| - } |
115 |
| - return MP_IMPORT_STAT_NO_EXIST; |
116 |
| -} |
117 |
| - |
118 |
| -mp_import_stat_t mp_frozen_stat(const char *str) { |
119 |
| - mp_import_stat_t stat; |
120 |
| - |
121 |
| - #if MICROPY_MODULE_FROZEN_STR |
122 |
| - stat = mp_frozen_stat_helper(mp_frozen_str_names, str); |
123 |
| - if (stat != MP_IMPORT_STAT_NO_EXIST) { |
124 |
| - return stat; |
| 128 | + // Skip null separator. |
| 129 | + name += entry_len + 1; |
125 | 130 | }
|
126 |
| - #endif |
127 |
| - |
128 |
| - #if MICROPY_MODULE_FROZEN_MPY |
129 |
| - stat = mp_frozen_stat_helper(mp_frozen_mpy_names, str); |
130 |
| - if (stat != MP_IMPORT_STAT_NO_EXIST) { |
131 |
| - return stat; |
132 |
| - } |
133 |
| - #endif |
134 | 131 |
|
135 | 132 | return MP_IMPORT_STAT_NO_EXIST;
|
136 | 133 | }
|
137 | 134 |
|
138 |
| -int mp_find_frozen_module(const char *str, size_t len, void **data) { |
139 |
| - #if MICROPY_MODULE_FROZEN_STR |
140 |
| - mp_lexer_t *lex = mp_lexer_frozen_str(str, len); |
141 |
| - if (lex != NULL) { |
142 |
| - *data = lex; |
143 |
| - return MP_FROZEN_STR; |
144 |
| - } |
145 |
| - #endif |
146 |
| - #if MICROPY_MODULE_FROZEN_MPY |
147 |
| - const mp_raw_code_t *rc = mp_find_frozen_mpy(str, len); |
148 |
| - if (rc != NULL) { |
149 |
| - *data = (void *)rc; |
150 |
| - return MP_FROZEN_MPY; |
151 |
| - } |
152 |
| - #endif |
153 |
| - return MP_FROZEN_NONE; |
154 |
| -} |
155 |
| - |
156 |
| -#endif |
| 135 | +#endif // MICROPY_MODULE_FROZEN |
0 commit comments