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  *
9  * Permission is hereby granted, free of charge, to any person obtaining a copy
10  * of this software and associated documentation files (the "Software"), to deal
11  * in the Software without restriction, including without limitation the rights
12  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13  * copies of the Software, and to permit persons to whom the Software is
14  * furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included in
17  * all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25  * THE SOFTWARE.
26  */
27 
28 #include <string.h>
29 #include <stdint.h>
30 
31 #include "py/lexer.h"
32 #include "py/frozenmod.h"
33 
34 #if MICROPY_MODULE_FROZEN_STR
35 
36 #ifndef MICROPY_MODULE_FROZEN_LEXER
37 #define MICROPY_MODULE_FROZEN_LEXER mp_lexer_new_from_str_len
38 #else
39 mp_lexer_t *MICROPY_MODULE_FROZEN_LEXER(qstr src_name, const char *str, mp_uint_t len, mp_uint_t free_len);
40 #endif
41 
42 extern const char mp_frozen_str_names[];
43 extern const uint32_t mp_frozen_str_sizes[];
44 extern const char mp_frozen_str_content[];
45 
46 // On input, *len contains size of name, on output - size of content
mp_find_frozen_str(const char * str,size_t * len)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 
mp_lexer_frozen_str(const char * str,size_t len)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
77 
78 #if MICROPY_MODULE_FROZEN_MPY
79 
80 #include "py/emitglue.h"
81 
82 extern const char mp_frozen_mpy_names[];
83 extern const mp_raw_code_t *const mp_frozen_mpy_content[];
84 
mp_find_frozen_mpy(const char * str,size_t len)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 }
96 
97 #endif
98 
99 #if MICROPY_MODULE_FROZEN
100 
mp_frozen_stat_helper(const char * name,const char * str)101 STATIC mp_import_stat_t mp_frozen_stat_helper(const char *name, const char *str) {
102     size_t len = strlen(str);
103 
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                 return MP_IMPORT_STAT_FILE;
109             } else if (name[len] == '/') {
110                 return MP_IMPORT_STAT_DIR;
111             }
112         }
113         name += l + 1;
114     }
115     return MP_IMPORT_STAT_NO_EXIST;
116 }
117 
mp_frozen_stat(const char * str)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;
125     }
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 
135     return MP_IMPORT_STAT_NO_EXIST;
136 }
137 
mp_find_frozen_module(const char * str,size_t len,void ** data)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
157