1 /*
2 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include <string.h>
10 #include <securec.h>
11 #include "hcs_file.h"
12 #include "hcs_compiler.h"
13 #include "hcs_gener.h"
14 #include "hcs_ast.h"
15 #include "hcs_option.h"
16
17 const char *g_nodeTypeStringMap[CONFIG_NODE_TYPE_COUNT] = {
18 [CONFIG_NODE_NOREF] = "NodeReference",
19 [CONFIG_NODE_COPY] = "NodeCopy",
20 [CONFIG_NODE_REF] = "NodeReference",
21 [CONFIG_NODE_DELETE] = "NodeDelete",
22 [CONFIG_NODE_INHERIT] = "NodeInherit",
23 [CONFIG_NODE_TEMPLATE] = "NodeTemplate",
24 };
25
HcsAlign(uint32_t size)26 uint32_t HcsAlign(uint32_t size)
27 {
28 if (HcsOptShouldAlign()) {
29 return (size + ALIGN_SIZE - 1) & (~(ALIGN_SIZE - 1));
30 } else {
31 return size;
32 }
33 }
34
HcsParserNodeTypeToStr(uint32_t nodeType)35 const char *HcsParserNodeTypeToStr(uint32_t nodeType)
36 {
37 if (nodeType >= CONFIG_NODE_TYPE_COUNT) {
38 return "";
39 }
40
41 return g_nodeTypeStringMap[nodeType];
42 }
43
HcsIsNumberObject(const ParserObject * obj)44 bool HcsIsNumberObject(const ParserObject *obj)
45 {
46 return obj->objectBase.type >= PARSEROP_UINT8 && obj->objectBase.type <= PARSEROP_UINT64;
47 }
48
HcsIsStringObject(const ParserObject * obj)49 bool HcsIsStringObject(const ParserObject *obj)
50 {
51 return obj->objectBase.type == PARSEROP_STRING;
52 }
53
HcsIsSameTypeObject(const ParserObject * cs,const ParserObject * ct)54 bool HcsIsSameTypeObject(const ParserObject *cs, const ParserObject *ct)
55 {
56 if (HcsIsNumberObject(cs)) {
57 return HcsIsNumberObject(ct);
58 } else if (cs->objectBase.type == PARSEROP_CONFTERM || cs->objectBase.type == PARSEROP_ARRAY) {
59 return ct->objectBase.type == cs->objectBase.type && cs->objectBase.child->type == ct->objectBase.child->type;
60 } else {
61 return ct->objectBase.type == cs->objectBase.type;
62 }
63 }
64
65 void HcsSetCompilerIn(FILE *in);
66
InitParser(const struct HcsFile * sourceFile)67 static void InitParser(const struct HcsFile *sourceFile)
68 {
69 HcsSetCompilerIn(sourceFile->file);
70 HcsParserRestart(sourceFile->file);
71 HcsSetCurrentSourceLine(1);
72 }
73
ParserCleanUp()74 void ParserCleanUp()
75 {
76 ParserObject *astRoot = HcsGetParserRoot();
77 HcsDeleteParserObjectTree(astRoot);
78 HcsSourceNameSetClean();
79 }
80
HcsProcessInclude(char * includePath,uint32_t lineNumber)81 int32_t HcsProcessInclude(char *includePath, uint32_t lineNumber)
82 {
83 if (includePath[0] == '/' || !strstr(includePath, HCS_SOURCE_FILE_SUFFIX)) {
84 HCS_ERROR("File:%s Line:%u\n\tinclude file %s is invalid", HcsGetCurrentSourceName(), lineNumber, includePath);
85 return EFAIL;
86 }
87
88 struct HcsFile *currentSource = HcsSourceQueueTop();
89 /* assembly include path to current source file */
90 uint32_t pathSize = strlen(currentSource->fullPath) + strlen(includePath) + 1;
91 char *path = HcsMemZalloc(pathSize);
92 if (path == NULL) {
93 HCS_ERROR("oom");
94 return EOOM;
95 }
96
97 if (HcsFileCopyDir(path, pathSize, currentSource->fullPath) != true) {
98 HcsMemFree(path);
99 return EFAIL;
100 }
101
102 int32_t res = strcat_s(path, pathSize, includePath);
103 if (res != EOK) {
104 HcsMemFree(path);
105 HCS_ERROR("%s:string cat fail", __func__);
106 return EFAIL;
107 }
108 HcsMemFree(includePath);
109
110 struct HcsFile *source = NULL;
111 uint32_t ret = HcsOpenSourceFile(path, &source, NULL);
112 if (ret == EREOPENF) {
113 HcsMemFree(path);
114 return NOERR;
115 }
116
117 if (ret) {
118 HCS_ERROR("File:%s Line:%u\n\tinclude file %s is invalid", HcsGetCurrentSourceName(), lineNumber, path);
119 HcsMemFree(path);
120 return EINVALF;
121 }
122
123 HcsSourceQueuePush(source);
124 HcsMemFree(path);
125 return NOERR;
126 }
127
HcsDoCompile(void)128 int32_t HcsDoCompile(void)
129 {
130 struct HcsFile *source = NULL;
131 char *forestName = strdup("ForestRoot");
132 if (forestName == NULL) {
133 return EOOM;
134 }
135 ParserObject *astForest = HcsNewParserObject(forestName, PARSEROP_CONFNODE, 0);
136 if (astForest == NULL) {
137 HcsMemFree(forestName);
138 return EFAIL;
139 }
140
141 uint32_t ret = HcsOpenSourceFile(HcsGetInputFileName(), &source, NULL);
142 if (ret) {
143 HCS_ERROR("Invalid source file: %s", HcsGetInputFileName());
144 HcsAstFreeObject(astForest);
145 return ret;
146 }
147 HcsSourceQueuePush(source);
148
149 /* parse specified source file and included files */
150 while (HcsSourceQueueSize()) {
151 source = HcsSourceQueueTop();
152 HCS_DEBUG("parsing file : %s%s", source->fullPath, source->name);
153 InitParser(source);
154
155 /* do parse */
156 ret = HcsCompilerparse();
157 ParserObject *currentRoot = HcsGetParserRoot();
158 /* pop current file, parse next file which maybe imported by include */
159 HcsSourceQueuePop();
160 HcsCloseFile(source);
161 if (ret) {
162 goto OUT;
163 }
164
165 HcsAstAddChild(astForest, currentRoot);
166 HcsSetParserRoot(NULL);
167 }
168 HcsSetParserRoot(astForest);
169
170 if (HcsVerbosePrint()) {
171 HcsDumpAst("Origin");
172 }
173
174 /* middle process */
175 ret = HcsDoOptimize();
176 if (ret) {
177 goto OUT;
178 }
179
180 /* output */
181 if (HcsOptShouldGenTextConfig()) {
182 ret = HcsTextCodeOutput();
183 } else if (HcsOptShouldGenByteCodeConfig()) {
184 ret = HcsBytecodeOutput();
185 }
186 OUT:
187 ParserCleanUp();
188 if (HcsGetParserRoot() != astForest) {
189 HcsDeleteParserObjectTree(astForest);
190 }
191 return ret;
192 }
193