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 <ctype.h>
11 #include <securec.h>
12 #include "hcs_ast.h"
13 #include "hcs_file.h"
14 #include "hcs_log.h"
15 #include "hcs_mem.h"
16 #include "hcs_option.h"
17 #include "hcs_parser.h"
18
19 #define TAB_SIZE 4
20 #define WRITE_BUFFER_LEN 256
21 #define VARIABLE_NAME_LEN 128
22 #define ELEMENT_PER_LINE 16
23 #define HCS_CONFIG_FILE_HEADER "/*\n" \
24 " * This is an automatically generated HDF config file. Do not modify it manually.\n" \
25 " */\n\n"
26
27 #define HCS_CONFIG_INCLUDE_HEADER "#include <stdint.h>\n\n"
28
29 #define DEFAULT_PREFIX "HdfConfig"
30
31 #define HCS_CONFIG_FUNC_IMPLEMENT "\nconst struct %s%sRoot* HdfGet%sModuleConfigRoot(void)\n" \
32 "{\n" \
33 " return &%s;\n" \
34 "}\n"
35
36 static char *g_configRootVariableName = NULL;
37 static char *g_bigHumpModuleName = NULL;
38 static const char *g_namePrefix = DEFAULT_PREFIX;
39 static char *g_littleHumpNamePrefix = NULL;
40
ToCamelString(char * str,uint32_t strLen)41 static void ToCamelString(char *str, uint32_t strLen)
42 {
43 if (!strLen) {
44 return;
45 }
46
47 if (strchr(str, '_') == NULL) {
48 return;
49 }
50
51 char *ptr = str;
52 char *processed = str;
53 uint32_t count = 0;
54 while (*ptr && count <= strLen) {
55 if (*ptr != '_') {
56 *processed++ = *ptr++;
57 } else {
58 ptr++;
59 *ptr = (char)toupper(*ptr);
60 }
61 count++;
62 }
63 *processed = '\0';
64 }
65
ToUpperCamelString(char * str,uint32_t strLen)66 static void ToUpperCamelString(char *str, uint32_t strLen)
67 {
68 if (!strLen) {
69 return;
70 }
71
72 ToCamelString(str, strLen);
73 str[0] = (char)toupper(str[0]);
74 }
75
ToLowerCamelString(char * str,uint32_t strLen)76 static void ToLowerCamelString(char *str, uint32_t strLen)
77 {
78 if (!strLen) {
79 return;
80 }
81
82 ToCamelString(str, strLen);
83 str[0] = (char)tolower(str[0]);
84 }
85
InitConfigVariableNames()86 static int32_t InitConfigVariableNames()
87 {
88 if (g_bigHumpModuleName == NULL) {
89 const char *moduleName = HcsGetModuleName();
90 g_bigHumpModuleName = HcsMemZalloc(strlen(moduleName) + 1);
91 if (g_bigHumpModuleName == NULL) {
92 return EOOM;
93 }
94 if (strcpy_s(g_bigHumpModuleName, strlen(moduleName) + 1, moduleName) != EOK) {
95 HCS_ERROR("failed to copy string");
96 return EFAIL;
97 }
98 ToUpperCamelString(g_bigHumpModuleName, strlen(g_bigHumpModuleName));
99 }
100 if (g_littleHumpNamePrefix == NULL) {
101 char *littleHumpPrefix = strdup(g_namePrefix);
102 if (littleHumpPrefix == NULL) {
103 return EOOM;
104 }
105 ToLowerCamelString(littleHumpPrefix, strlen(littleHumpPrefix));
106 g_littleHumpNamePrefix = littleHumpPrefix;
107 }
108 if (g_configRootVariableName == NULL) {
109 const uint32_t nameLen = VARIABLE_NAME_LEN;
110 g_configRootVariableName = HcsMemZalloc(nameLen);
111 if (g_configRootVariableName == NULL) {
112 return EOOM;
113 }
114
115 int32_t ret = sprintf_s(g_configRootVariableName, nameLen, "g_%s%sModuleRoot", g_littleHumpNamePrefix,
116 g_bigHumpModuleName);
117 if (ret <= 0) {
118 return EFAIL;
119 }
120 }
121
122 return NOERR;
123 }
124
ReleaseConfigVariableNames()125 static void ReleaseConfigVariableNames()
126 {
127 if (g_configRootVariableName != NULL) {
128 HcsMemFree(g_configRootVariableName);
129 g_configRootVariableName = NULL;
130 }
131
132 if (g_bigHumpModuleName != NULL) {
133 HcsMemFree(g_bigHumpModuleName);
134 g_bigHumpModuleName = NULL;
135 }
136
137 if (g_littleHumpNamePrefix != NULL) {
138 HcsMemFree(g_littleHumpNamePrefix);
139 g_littleHumpNamePrefix = NULL;
140 }
141 }
142
GetConfigRootVariableName()143 static const char *GetConfigRootVariableName()
144 {
145 return g_configRootVariableName;
146 }
147
148 typedef struct HcsSymbol {
149 char *name;
150 const ParserObject *object;
151 uint32_t duplicateCount;
152 struct HcsSymbol *left;
153 struct HcsSymbol *right;
154 struct HcsSymbol *parent;
155 } HcsSymbol;
156
157 typedef struct HcsSymbolTable {
158 HcsSymbol *symbols;
159 uint32_t size;
160 } HcsSymbolTable;
161
162 static HcsSymbolTable *g_hcsSymbolTable = NULL;
163 static int32_t HcsImplementGenWalkCallBack(ParserObject *current, int32_t walkDepth);
164 static int32_t HcsImplementCloseBraceGen(ParserObject *current, int32_t walkDepth);
165
HcsIsInSubClassNode(const ParserObject * object)166 static bool HcsIsInSubClassNode(const ParserObject *object)
167 {
168 while (object != NULL) {
169 if (object->configNode.nodeType == CONFIG_NODE_INHERIT) {
170 return true;
171 }
172 object = (ParserObject *)object->objectBase.parent;
173 }
174 return false;
175 }
176
HcsIsInTemplateNode(const ParserObject * object)177 static bool HcsIsInTemplateNode(const ParserObject *object)
178 {
179 while (object != NULL) {
180 if (object->configNode.nodeType == CONFIG_NODE_TEMPLATE) {
181 return true;
182 }
183 object = (ParserObject *)object->objectBase.parent;
184 }
185 return false;
186 }
187
HcsReleaseSymbol(struct HcsSymbol * s)188 static void HcsReleaseSymbol(struct HcsSymbol *s)
189 {
190 if (s == NULL) {
191 return;
192 }
193 if (s->left != NULL) {
194 HcsReleaseSymbol(s->left);
195 s->left = NULL;
196 }
197 if (s->right != NULL) {
198 HcsReleaseSymbol(s->right);
199 s->right = NULL;
200 }
201 HcsMemFree(s->name);
202 HcsMemFree(s);
203 }
204
HcsSymbolTableRelease()205 static void HcsSymbolTableRelease()
206 {
207 HcsReleaseSymbol(g_hcsSymbolTable->symbols);
208 HcsMemFree(g_hcsSymbolTable);
209 g_hcsSymbolTable = NULL;
210 }
211
HcsNewSymbol(const char * name,const ParserObject * object)212 static HcsSymbol *HcsNewSymbol(const char *name, const ParserObject *object)
213 {
214 HcsSymbol *newSymbol = HcsMemZalloc(sizeof(HcsSymbol));
215 if (newSymbol == NULL) {
216 HCS_ERROR("oom");
217 return NULL;
218 }
219 char *symbolName = strdup(name);
220 if (symbolName == NULL) {
221 HcsMemFree(newSymbol);
222 return NULL;
223 }
224 newSymbol->name = symbolName;
225 newSymbol->object = object;
226 newSymbol->duplicateCount = 1;
227
228 return newSymbol;
229 }
HcsSymbolTableInit()230 static int32_t HcsSymbolTableInit()
231 {
232 if (g_hcsSymbolTable != NULL) {
233 HcsSymbolTableRelease();
234 }
235
236 g_hcsSymbolTable = HcsMemZalloc(sizeof(HcsSymbolTable));
237 return (g_hcsSymbolTable != NULL) ? NOERR : EOOM;
238 }
239
HcsSymbolTableReset()240 static int32_t HcsSymbolTableReset()
241 {
242 HcsSymbolTableRelease();
243 return HcsSymbolTableInit();
244 }
245
HcsSymbolTableAdd(const char * name,const ParserObject * object)246 int32_t HcsSymbolTableAdd(const char *name, const ParserObject *object)
247 {
248 HcsSymbol *symbolRoot = g_hcsSymbolTable->symbols;
249 HcsSymbol *newSymbol = HcsNewSymbol(name, object);
250 if (newSymbol == NULL) {
251 return EOOM;
252 }
253 int32_t cmpRes;
254 HcsSymbol *insert = NULL;
255 HcsSymbol *p = symbolRoot;
256 while (p != NULL) {
257 insert = p;
258 cmpRes = strcasecmp(name, p->name);
259 if (!cmpRes) {
260 HCS_OBJECT_ERROR(object,
261 "duplicate node name at %s:%u\n To avoid redefining structures,"
262 " not allow duplicate node name at text config mode",
263 p->object->objectBase.src, p->object->objectBase.lineno);
264 HcsReleaseSymbol(newSymbol);
265 return EINVALARG;
266 }
267 p = cmpRes < 0 ? p->left : p->right;
268 }
269
270 if (insert == NULL) {
271 g_hcsSymbolTable->symbols = newSymbol;
272 } else if (cmpRes < 0) {
273 insert->left = newSymbol;
274 } else {
275 insert->right = newSymbol;
276 }
277
278 g_hcsSymbolTable->size++;
279
280 return NOERR;
281 }
282
HcsSymbolTableFind(const char * name)283 HcsSymbol *HcsSymbolTableFind(const char *name)
284 {
285 HcsSymbol *p = g_hcsSymbolTable->symbols;
286 while (p != NULL) {
287 int32_t cmpRes = strcasecmp(name, p->name);
288 if (cmpRes == 0) {
289 return p;
290 }
291 p = cmpRes < 0 ? p->left : p->right;
292 }
293
294 return NULL;
295 }
296
297 const char *g_typeMap[PARSEROP_COUNT] = {
298 [PARSEROP_UINT8] = "uint8_t",
299 [PARSEROP_UINT16] = "uint16_t",
300 [PARSEROP_UINT32] = "uint32_t",
301 [PARSEROP_UINT64] = "uint64_t",
302 [PARSEROP_STRING] = "const char*",
303 };
304
GenConfigStructName(const ParserObject * node,char * name,uint32_t nameBuffLen)305 static int32_t GenConfigStructName(const ParserObject *node, char *name, uint32_t nameBuffLen)
306 {
307 char nameBuffer[OBJECT_NAME_MAX_LEN] = {'\0'};
308 if (strcpy_s(nameBuffer, OBJECT_NAME_MAX_LEN, HcsGetModuleName()) != EOK) {
309 return EOUTPUT;
310 }
311 ToUpperCamelString(nameBuffer, strlen(nameBuffer));
312 int32_t res = sprintf_s(name, nameBuffLen, "%s%s", g_namePrefix, nameBuffer);
313 PRINTF_CHECK_AND_RETURN(res);
314
315 if (strcpy_s(nameBuffer, OBJECT_NAME_MAX_LEN, node->configNode.name) != EOK) {
316 return EOUTPUT;
317 }
318 ToUpperCamelString(nameBuffer, strlen(nameBuffer));
319 res = sprintf_s(name + strlen(name), nameBuffLen - strlen(name), "%s", nameBuffer);
320 PRINTF_CHECK_AND_RETURN(res);
321
322 return NOERR;
323 }
324
GenConfigArrayName(ParserObject * array,char * name,uint32_t nameBuffLen)325 static int32_t GenConfigArrayName(ParserObject *array, char *name, uint32_t nameBuffLen)
326 {
327 char buffer[OBJECT_NAME_MAX_LEN] = {'\0'};
328
329 if (strcpy_s(buffer, sizeof(buffer), array->objectBase.name) != EOK) {
330 HCS_ERROR("%s: failed to copy string", __func__);
331 return EOUTPUT;
332 }
333 ToUpperCamelString(buffer, strlen(buffer));
334
335 int32_t ret = sprintf_s(name, nameBuffLen, "g_hcsConfigArray%s", buffer);
336 PRINTF_CHECK_AND_RETURN(ret);
337
338 HcsSymbol *symbol = HcsSymbolTableFind(name);
339 if (symbol == NULL) {
340 if (HcsSymbolTableAdd(name, array)) {
341 return EFAIL;
342 }
343 array->configTerm.signNum = 1;
344 } else if (!array->configTerm.signNum) {
345 array->configTerm.signNum = symbol->duplicateCount + 1;
346 symbol->duplicateCount++;
347 }
348
349 ret = sprintf_s(name + strlen(name), nameBuffLen - strlen(name), "%d", array->configTerm.signNum);
350 PRINTF_CHECK_AND_RETURN(ret);
351 return NOERR;
352 }
353
GetArrayType(const ParserObject * array)354 static const char *GetArrayType(const ParserObject *array)
355 {
356 uint32_t type = PARSEROP_UINT8;
357 ParserObject *element = (ParserObject *)array->objectBase.child;
358 while (element != NULL) {
359 type = element->objectBase.type > type ? element->objectBase.type : type;
360 element = (ParserObject *)element->objectBase.next;
361 }
362
363 return g_typeMap[type];
364 }
365
GetArraySize(const ParserObject * array)366 static int32_t GetArraySize(const ParserObject *array)
367 {
368 uint32_t size = 0;
369 ParserObjectBase *element = array->objectBase.child;
370 while (element != NULL) {
371 size++;
372 element = element->next;
373 }
374 return size;
375 }
376
HcsPrintTermDefinition(const ParserObject * object)377 static int32_t HcsPrintTermDefinition(const ParserObject *object)
378 {
379 ParserObject *termContext = (ParserObject *)object->objectBase.child;
380 int32_t res = NOERR;
381 switch (termContext->objectBase.type) {
382 case PARSEROP_ARRAY:
383 if (HcsIsInTemplateNode(object)) {
384 res = HcsFormatOutputWrite("const %s *%s;\n", GetArrayType(termContext), object->configTerm.name);
385 OUTPUT_CHECK_AND_RETURN(res);
386 res = HcsFormatOutputWrite("%*cuint32_t %sSize;\n", TAB_SIZE, ' ', object->configTerm.name);
387 } else {
388 res = HcsFormatOutputWrite("%s %s[%d];\n", GetArrayType(termContext), object->configTerm.name,
389 GetArraySize(termContext));
390 }
391 break;
392 case PARSEROP_UINT8:
393 case PARSEROP_UINT16:
394 case PARSEROP_UINT32:
395 case PARSEROP_UINT64:
396 case PARSEROP_STRING:
397 res = HcsFormatOutputWrite("%s %s;\n", g_typeMap[termContext->objectBase.type], object->configTerm.name);
398 break;
399 case PARSEROP_NODEREF: {
400 char refType[OBJECT_NAME_MAX_LEN] = {'\0'};
401 res = GenConfigStructName((ParserObject *)termContext->objectBase.value, refType, OBJECT_NAME_MAX_LEN - 1);
402 if (res) {
403 return res;
404 }
405 res = HcsFormatOutputWrite("const struct %s* %s;\n", refType, object->configTerm.name);
406 } break;
407 default:
408 break;
409 }
410
411 return res;
412 }
413
HcsObjectDefinitionGen(const ParserObject * current)414 static int32_t HcsObjectDefinitionGen(const ParserObject *current)
415 {
416 if (current->objectBase.type != PARSEROP_CONFNODE && current->objectBase.type != PARSEROP_CONFTERM) {
417 return NOERR;
418 }
419
420 int res = NOERR;
421 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("%*c", TAB_SIZE, ' '));
422 switch (current->objectBase.type) {
423 case PARSEROP_CONFNODE: {
424 char structName[OBJECT_NAME_MAX_LEN] = {'\0'};
425 res = GenConfigStructName(current, structName, OBJECT_NAME_MAX_LEN - 1);
426 if (res) {
427 return res;
428 }
429 if (current->configNode.nodeType == CONFIG_NODE_TEMPLATE) {
430 char nodeName[OBJECT_NAME_MAX_LEN] = {0};
431 if (strcpy_s(nodeName, sizeof(nodeName), current->configNode.name) != EOK) {
432 return EOUTPUT;
433 }
434 ToLowerCamelString(nodeName, strlen(nodeName));
435 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("const struct %s* %s;\n", structName, nodeName));
436 res = HcsFormatOutputWrite("%*cuint16_t %sSize;\n", TAB_SIZE, ' ', nodeName);
437 } else if (current->configNode.nodeType == CONFIG_NODE_INHERIT) {
438 return NOERR;
439 } else {
440 res = HcsFormatOutputWrite("struct %s %s;\n", structName, current->configNode.name);
441 }
442 break;
443 }
444 case PARSEROP_CONFTERM:
445 res = HcsPrintTermDefinition(current);
446 break;
447 default:
448 break;
449 }
450
451 return res;
452 }
453
HcsDuplicateCheckWalkCallBack(ParserObject * current,int32_t walkDepth)454 static int32_t HcsDuplicateCheckWalkCallBack(ParserObject *current, int32_t walkDepth)
455 {
456 (void)walkDepth;
457 if (current->objectBase.type != PARSEROP_CONFNODE || HcsIsInSubClassNode(current)) {
458 return NOERR;
459 }
460
461 return HcsSymbolTableAdd(current->objectBase.name, current);
462 }
463
HcsGenNormalNodeDefinition(ParserObject * object,int32_t walkDepth)464 static int32_t HcsGenNormalNodeDefinition(ParserObject *object, int32_t walkDepth)
465 {
466 (void)walkDepth;
467 char structName[OBJECT_NAME_MAX_LEN] = {'\0'};
468 int32_t res = GenConfigStructName(object, structName, OBJECT_NAME_MAX_LEN - 1);
469 if (res) {
470 return res;
471 }
472 if (HcsSymbolTableFind(structName)) {
473 return NOERR;
474 } else {
475 HcsSymbolTableAdd(structName, object);
476 }
477
478 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("struct %s {\n", structName));
479
480 ParserObject *terms = (ParserObject *)object->objectBase.child;
481 while (terms != NULL) {
482 res = HcsObjectDefinitionGen(terms);
483 if (res) {
484 return res;
485 }
486 terms = (ParserObject *)terms->objectBase.next;
487 }
488
489 return HcsFormatOutputWrite("};\n\n");
490 }
491
HcsGenNodeTemplateDefinition(ParserObject * object,int32_t walkDepth)492 static int32_t HcsGenNodeTemplateDefinition(ParserObject *object, int32_t walkDepth)
493 {
494 return HcsGenNormalNodeDefinition(object, walkDepth);
495 }
496
HcsDefinitionGenWalkCallBack(ParserObject * current,int32_t walkDepth)497 static int32_t HcsDefinitionGenWalkCallBack(ParserObject *current, int32_t walkDepth)
498 {
499 (void)walkDepth;
500 if (current->objectBase.type != PARSEROP_CONFNODE) {
501 return NOERR;
502 }
503 if (current->configNode.nodeType == CONFIG_NODE_TEMPLATE) {
504 return HcsGenNodeTemplateDefinition(current, walkDepth);
505 } else if (current->configNode.nodeType == CONFIG_NODE_INHERIT) {
506 return NOERR;
507 } else {
508 return HcsGenNormalNodeDefinition(current, walkDepth);
509 }
510 }
511
HcsPrintTermValue(const ParserObject * object)512 static uint32_t HcsPrintTermValue(const ParserObject *object)
513 {
514 int32_t res = NOERR;
515 switch (object->objectBase.type) {
516 case PARSEROP_UINT8: /* fallthrough */
517 case PARSEROP_UINT16: /* fallthrough */
518 case PARSEROP_UINT32: /* fallthrough */
519 case PARSEROP_UINT64:
520 res = HcsFormatOutputWrite("0x%" PRIx64, object->objectBase.integerValue);
521 break;
522 case PARSEROP_STRING:
523 res = HcsFormatOutputWrite("\"%s\"", object->objectBase.stringValue);
524 break;
525 default:
526 break;
527 }
528
529 return res;
530 }
531
532 #define MAX_CONFIG_TREE_DEPTH 100
HcsBuildObjectPath(const ParserObject * refObject)533 static char *HcsBuildObjectPath(const ParserObject *refObject)
534 {
535 const char *pathArray[MAX_CONFIG_TREE_DEPTH] = {0};
536 int32_t count = 0;
537 size_t pathStringLen = strlen(GetConfigRootVariableName()) + 1;
538 const ParserObject *it = refObject;
539
540 while (it != HcsGetParserRoot() && count < MAX_CONFIG_TREE_DEPTH) {
541 pathArray[count++] = it->objectBase.name;
542 pathStringLen += strlen(it->objectBase.name) + 1;
543 it = (ParserObject *)it->objectBase.parent;
544 }
545 if (count >= MAX_CONFIG_TREE_DEPTH) {
546 HCS_ERROR("reference a config node nested too deep over %u", MAX_CONFIG_TREE_DEPTH);
547 return NULL;
548 }
549
550 char *path = HcsMemZalloc(pathStringLen);
551 if (path == NULL) {
552 HCS_ERROR("%s:oom", __func__);
553 return NULL;
554 }
555
556 int32_t res = strcat_s(path, pathStringLen, GetConfigRootVariableName());
557 if (res) {
558 HcsMemFree(path);
559 HCS_ERROR("%s:string cat fail", __func__);
560 return NULL;
561 }
562
563 for (int32_t i = count - 1; i >= 0; --i) {
564 res = strcat_s(path, pathStringLen, ".");
565 if (res) {
566 HcsMemFree(path);
567 HCS_ERROR("%s:string cat fail", __func__);
568 return NULL;
569 }
570 res = strcat_s(path, pathStringLen, pathArray[i]);
571 if (res) {
572 HcsMemFree(path);
573 HCS_ERROR("%s:string cat fail", __func__);
574 return NULL;
575 }
576 }
577
578 return path;
579 }
580
HcsPrintArrayImplInSubClass(ParserObject * object,uint8_t tabSize)581 static int32_t HcsPrintArrayImplInSubClass(ParserObject *object, uint8_t tabSize)
582 {
583 char arrayName[VARIABLE_NAME_LEN] = {0};
584 if (GenConfigArrayName(object, arrayName, VARIABLE_NAME_LEN)) {
585 return EOUTPUT;
586 }
587 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite(".%s = %s,\n", object->objectBase.name, arrayName));
588 return HcsFormatOutputWrite("%*c.%sSize = %d,\n", tabSize, ' ',
589 object->configTerm.name, GetArraySize((ParserObject *)object->objectBase.child));
590 }
591
HcsPrintArrayContent(const ParserObject * object,int32_t tabSize)592 static int32_t HcsPrintArrayContent(const ParserObject *object, int32_t tabSize)
593 {
594 if (!GetArraySize(object)) {
595 return NOERR;
596 }
597
598 ParserObject *element = (ParserObject *)object->objectBase.child;
599 uint32_t elementCount = 0;
600 while (element != NULL) {
601 if (HcsPrintTermValue(element) != NOERR) {
602 return EOUTPUT;
603 }
604 if (elementCount++ >= ELEMENT_PER_LINE) {
605 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("\n%*c", tabSize, ' '));
606 }
607 element = (ParserObject *)element->configTerm.next;
608 if (element != NULL) {
609 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite(", "));
610 }
611 }
612
613 return NOERR;
614 }
615
HcsPrintArrayImplement(ParserObject * object,uint8_t tabSize)616 static int32_t HcsPrintArrayImplement(ParserObject *object, uint8_t tabSize)
617 {
618 if (HcsIsInSubClassNode(object)) {
619 return HcsPrintArrayImplInSubClass(object, tabSize);
620 }
621
622 ParserObject *termContext = (ParserObject *)object->objectBase.child;
623 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite(".%s = { ", object->configTerm.name));
624
625 if (HcsPrintArrayContent(termContext, tabSize + TAB_SIZE)) {
626 HCS_ERROR("fail to write array content");
627 return EOUTPUT;
628 }
629 return HcsFormatOutputWrite(" },\n");
630 }
631
HcsPrintTermImplement(ParserObject * object,int32_t tabSize)632 static int32_t HcsPrintTermImplement(ParserObject *object, int32_t tabSize)
633 {
634 int32_t res = NOERR;
635 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("%*c", tabSize, ' '));
636 ParserObject *termContext = (ParserObject *)object->objectBase.child;
637 switch (termContext->objectBase.type) {
638 case PARSEROP_UINT8:
639 /* fall-through */
640 case PARSEROP_UINT16:
641 /* fall-through */
642 case PARSEROP_UINT32:
643 /* fall-through */
644 case PARSEROP_UINT64:
645 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite(".%s = ", object->configTerm.name));
646 if (HcsPrintTermValue(termContext) != NOERR) {
647 return EOUTPUT;
648 }
649 res = HcsFormatOutputWrite(",\n");
650 break;
651 case PARSEROP_STRING:
652 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite(".%s = ", object->configTerm.name));
653 if (HcsPrintTermValue(termContext) != NOERR) {
654 return EOUTPUT;
655 }
656 res = HcsFormatOutputWrite(",\n");
657 break;
658 case PARSEROP_ARRAY:
659 res = HcsPrintArrayImplement(object, tabSize);
660 break;
661 case PARSEROP_NODEREF: {
662 char *refPath = HcsBuildObjectPath((ParserObject *)object->objectBase.child->value);
663 if (refPath == NULL) {
664 return EOUTPUT;
665 }
666 res = HcsFormatOutputWrite(".%s = &%s,\n", object->configTerm.name, refPath);
667 HcsMemFree(refPath);
668 break;
669 }
670 default:
671 break;
672 }
673
674 return res;
675 }
676
HcsGenTemplateVariableName(ParserObject * object,char * nameBuff,uint32_t nameBufferSize)677 static int32_t HcsGenTemplateVariableName(ParserObject *object, char *nameBuff, uint32_t nameBufferSize)
678 {
679 char tempName[OBJECT_NAME_MAX_LEN] = {'\0'};
680 if (strcpy_s(tempName, sizeof(tempName), object->objectBase.name) != EOK) {
681 HCS_ERROR("failed to copy string");
682 return EOUTPUT;
683 }
684 ToUpperCamelString(tempName, sizeof(tempName));
685 HcsSymbol *sym = HcsSymbolTableFind(object->objectBase.name);
686 if (sym == NULL) {
687 HcsSymbolTableAdd(object->objectBase.name, object);
688 } else if (sym->object != object && object->configNode.templateSignNum == 0) {
689 sym->duplicateCount++;
690 object->configNode.templateSignNum = sym->duplicateCount;
691 }
692
693 int32_t res;
694 if (object->configNode.templateSignNum) {
695 res = sprintf_s(nameBuff, nameBufferSize, "g_%s%s%d", g_littleHumpNamePrefix, tempName,
696 object->configNode.templateSignNum);
697 } else {
698 res = sprintf_s(nameBuff, nameBufferSize, "g_%s%s", g_littleHumpNamePrefix, tempName);
699 }
700
701 return (res > 0) ? NOERR : EFAIL;
702 }
703
HcsTemplateNodeImplGen(ParserObject * current,int32_t tabSize)704 static int32_t HcsTemplateNodeImplGen(ParserObject *current, int32_t tabSize)
705 {
706 char templateVariableName[VARIABLE_NAME_LEN] = {'\0'};
707 if (HcsGenTemplateVariableName(current, templateVariableName, sizeof(templateVariableName))) {
708 return EOUTPUT;
709 }
710 char nodeName[OBJECT_NAME_MAX_LEN] = {0};
711 if (strcpy_s(nodeName, sizeof(nodeName), current->configNode.name) != EOK) {
712 HCS_ERROR("%s: failed to copy string", __func__);
713 return EOUTPUT;
714 }
715
716 ToLowerCamelString(nodeName, strlen(nodeName));
717 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("%*c.%s = %s,\n", tabSize, ' ', nodeName,
718 current->configNode.inheritCount ? templateVariableName : "0"));
719
720 return HcsFormatOutputWrite("%*c.%sSize = %d,\n",
721 tabSize, ' ', nodeName, current->configNode.inheritCount);
722 }
723
HcsInheritObjectImplGen(ParserObject * current,int32_t tabSize)724 static int32_t HcsInheritObjectImplGen(ParserObject *current, int32_t tabSize)
725 {
726 if (current->configNode.nodeType == CONFIG_NODE_TEMPLATE) {
727 return HcsTemplateNodeImplGen(current, tabSize);
728 }
729
730 return NOERR;
731 }
732
HcsObjectImplementGen(ParserObject * current,int32_t tabSize)733 static int32_t HcsObjectImplementGen(ParserObject *current, int32_t tabSize)
734 {
735 int32_t res = NOERR;
736 switch (current->objectBase.type) {
737 case PARSEROP_CONFNODE:
738 if (current->configNode.nodeType != CONFIG_NODE_NOREF) {
739 res = HcsInheritObjectImplGen(current, tabSize);
740 return res ? res : EASTWALKBREAK;
741 }
742 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("%*c.%s = {\n", tabSize, ' ', current->configNode.name));
743 if (current->objectBase.child == NULL) {
744 res = HcsFormatOutputWrite("%*c},\n", tabSize, ' ');
745 }
746 break;
747 case PARSEROP_CONFTERM:
748 res = HcsPrintTermImplement(current, tabSize);
749 break;
750 default:
751 return NOERR;
752 }
753
754 return res;
755 }
756
HcsImplementGenWalkCallBack(ParserObject * current,int32_t walkDepth)757 static int32_t HcsImplementGenWalkCallBack(ParserObject *current, int32_t walkDepth)
758 {
759 if (current->objectBase.type != PARSEROP_CONFNODE && current->objectBase.type != PARSEROP_CONFTERM) {
760 return NOERR;
761 }
762
763 if (current->objectBase.type != PARSEROP_CONFNODE && HcsIsInSubClassNode(current)) {
764 return NOERR;
765 }
766
767 if (current == HcsGetParserRoot()) {
768 char structName[OBJECT_NAME_MAX_LEN] = {'\0'};
769 int32_t res = GenConfigStructName(current, structName, OBJECT_NAME_MAX_LEN - 1);
770 if (res) {
771 return res;
772 }
773 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("static const struct %s %s = {\n",
774 structName, GetConfigRootVariableName()));
775 if (current->objectBase.child == NULL) {
776 res = HcsFormatOutputWrite("};\n");
777 }
778 return res;
779 }
780 return HcsObjectImplementGen(current, walkDepth * TAB_SIZE);
781 }
782
HcsImplementCloseBraceGen(ParserObject * current,int32_t walkDepth)783 static int32_t HcsImplementCloseBraceGen(ParserObject *current, int32_t walkDepth)
784 {
785 if (current->objectBase.type != PARSEROP_CONFNODE) {
786 return NOERR;
787 }
788
789 if (current->configNode.nodeType == CONFIG_NODE_INHERIT) {
790 return NOERR;
791 }
792
793 int32_t tabSize = walkDepth * TAB_SIZE;
794
795 if (current != HcsGetParserRoot()) {
796 return HcsFormatOutputWrite("%*c},\n", tabSize, ' ');
797 } else {
798 return HcsFormatOutputWrite("};\n");
799 }
800 }
801
ToUpperString(char * str,uint32_t strLen)802 static void ToUpperString(char *str, uint32_t strLen)
803 {
804 for (uint32_t i = 0; i < strLen; ++i) {
805 str[i] = (char)toupper(str[i]);
806 }
807 }
808
809 #define HCS_HEADER_MACRO_MAX_LEN 150
GenHeaderProtectionMacro()810 static char *GenHeaderProtectionMacro()
811 {
812 char *fileName = HcsGetOutputFileNameWithoutSuffix();
813 if (fileName == NULL) {
814 return NULL;
815 }
816 ToUpperString(fileName, strlen(fileName));
817
818 char *macro = HcsMemZalloc(sizeof(char) * HCS_HEADER_MACRO_MAX_LEN);
819 if (macro == NULL) {
820 HCS_ERROR("oom");
821 HcsMemFree(fileName);
822 return NULL;
823 }
824
825 int32_t res = sprintf_s(macro, HCS_HEADER_MACRO_MAX_LEN, "HCS_CONFIG_%s_HEADER_H", fileName);
826 HcsMemFree(fileName);
827 if (res <= 0) {
828 HcsMemFree(macro);
829 return NULL;
830 }
831 return macro;
832 }
833
HcsWriteHeaderFileHead()834 static int32_t HcsWriteHeaderFileHead()
835 {
836 /* Write copyright info */
837 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite(HCS_CONFIG_FILE_HEADER));
838
839 /* Write header protection macro */
840 char *headerProtectMacro = GenHeaderProtectionMacro();
841 if (headerProtectMacro == NULL) {
842 return EOUTPUT;
843 }
844 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("#ifndef %s\n#define %s\n\n",
845 headerProtectMacro, headerProtectMacro));
846
847 /* Write include header file */
848 return HcsFormatOutputWrite(HCS_CONFIG_INCLUDE_HEADER);
849 }
850
HcsWriteHeaderFileEnd()851 static int32_t HcsWriteHeaderFileEnd()
852 {
853 /* Write header protection macro */
854 char *headerMacro = GenHeaderProtectionMacro();
855 if (headerMacro == NULL) {
856 return EOUTPUT;
857 }
858 int32_t ret = HcsFormatOutputWrite("\n\n#endif // %s", headerMacro);
859 HcsMemFree(headerMacro);
860
861 return ret;
862 }
863
HcsWriteFunctionDeclaration()864 static int32_t HcsWriteFunctionDeclaration()
865 {
866 return HcsFormatOutputWrite("const struct %s%sRoot* HdfGet%sModuleConfigRoot(void);", g_namePrefix,
867 g_bigHumpModuleName, g_bigHumpModuleName);
868 }
869
HcsWriteFunctionImplement()870 static int32_t HcsWriteFunctionImplement()
871 {
872 return HcsFormatOutputWrite(HCS_CONFIG_FUNC_IMPLEMENT, g_namePrefix,
873 g_bigHumpModuleName, g_bigHumpModuleName, GetConfigRootVariableName());
874 }
875
HcsOutputHeaderFile()876 static int32_t HcsOutputHeaderFile()
877 {
878 struct HcsFile *outputFIle = NULL;
879 ParserObject *astRoot = HcsGetParserRoot();
880 if (astRoot == NULL) {
881 return EOUTPUT;
882 }
883
884 /* Duplicate node name check */
885 if (HcsWalkAst(astRoot, AST_WALK_BACKEND, NULL, HcsDuplicateCheckWalkCallBack)) {
886 return EOUTPUT;
887 }
888
889 outputFIle = HcsOpenOutputFile(".h");
890 if (outputFIle == NULL) {
891 return EINVALF;
892 }
893
894 int32_t ret = HcsWriteHeaderFileHead();
895 if (ret) {
896 goto OUT;
897 }
898 /* Generate C header file containing the structure definition of config */
899 if (!HcsWalkAst(astRoot, AST_WALK_BACKEND, NULL, HcsDefinitionGenWalkCallBack)) {
900 ret = HcsWriteFunctionDeclaration();
901 if (ret) {
902 goto OUT;
903 }
904 }
905
906 ret = HcsWriteHeaderFileEnd();
907 OUT:
908 HcsCloseOutput(outputFIle);
909 return ret;
910 }
911
912
913 static int32_t g_baseTabsize = 0;
914
HcsTemplateObjectGenWalk(ParserObject * current,int32_t walkDepth)915 static int32_t HcsTemplateObjectGenWalk(ParserObject *current, int32_t walkDepth)
916 {
917 return HcsObjectImplementGen(current, walkDepth * TAB_SIZE + g_baseTabsize);
918 }
919
HcsTemplateCloseBraceGen(ParserObject * current,int32_t walkDepth)920 static int32_t HcsTemplateCloseBraceGen(ParserObject *current, int32_t walkDepth)
921 {
922 return HcsImplementCloseBraceGen(current, walkDepth + g_baseTabsize / TAB_SIZE);
923 }
924
HcsTemplateVariableGen(ParserObject * current)925 static int32_t HcsTemplateVariableGen(ParserObject *current)
926 {
927 ParserObject *child = (ParserObject *)current->objectBase.child;
928 while (child != NULL) {
929 int32_t res = HcsWalkAst(child, AST_WALK_ROUND, HcsTemplateObjectGenWalk, HcsTemplateCloseBraceGen);
930 if (res) {
931 return res;
932 }
933 child = (ParserObject *)child->objectBase.next;
934 }
935 return NOERR;
936 }
937
HcsTemplateImplGenWalkCallBack(ParserObject * current,int32_t walkDepth)938 static int32_t HcsTemplateImplGenWalkCallBack(ParserObject *current, int32_t walkDepth)
939 {
940 (void)walkDepth;
941 if (current->objectBase.type != PARSEROP_CONFNODE || current->configNode.nodeType != CONFIG_NODE_TEMPLATE) {
942 return NOERR;
943 }
944
945 if (!current->configNode.inheritCount) {
946 return NOERR;
947 }
948
949 char nameBuff[OBJECT_NAME_MAX_LEN] = {'\0'};
950 int32_t res = GenConfigStructName(current, nameBuff, OBJECT_NAME_MAX_LEN - 1);
951 if (res) {
952 return res;
953 }
954
955 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("static const struct %s ", nameBuff));
956 if (HcsGenTemplateVariableName(current, nameBuff, sizeof(nameBuff))) {
957 return EOUTPUT;
958 }
959 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("%s[] = {\n", nameBuff));
960
961 /* Generate C global variables definition file */
962 TemplateNodeInstance *subClasses = current->configNode.subClasses;
963 g_baseTabsize = TAB_SIZE + TAB_SIZE;
964 while (subClasses != NULL) {
965 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("%*c[%d] = {\n", TAB_SIZE, ' ',
966 subClasses->nodeObject->inheritIndex));
967
968 if (HcsTemplateVariableGen((ParserObject *)subClasses->nodeObject)) {
969 return EOUTPUT;
970 }
971 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("%*c},\n", TAB_SIZE, ' '));
972 subClasses = subClasses->next;
973 }
974
975 return HcsFormatOutputWrite("};\n\n");
976 }
977
HcsArrayVariablesDeclareGen(ParserObject * term)978 static int32_t HcsArrayVariablesDeclareGen(ParserObject *term)
979 {
980 if (!HcsIsInSubClassNode(term)) {
981 return NOERR;
982 }
983
984 char nameBuff[OBJECT_NAME_MAX_LEN] = {'\0'};
985 int32_t res = GenConfigArrayName(term, nameBuff, OBJECT_NAME_MAX_LEN - 1);
986 if (res) {
987 return res;
988 }
989 ParserObject *array = (ParserObject *)term->configTerm.child;
990 res = HcsFormatOutputWrite("\nstatic const %s %s[%d] = {\n%*c", GetArrayType(array),
991 nameBuff, GetArraySize(array), TAB_SIZE, ' ');
992 OUTPUT_CHECK_AND_RETURN(res);
993
994 if (HcsPrintArrayContent(array, TAB_SIZE)) {
995 HCS_ERROR("fail to write array content");
996 return EOUTPUT;
997 }
998 return HcsFormatOutputWrite("\n};\n");
999 }
1000
HcsTemplateVariablesDeclareGenWalk(ParserObject * current,int32_t walkDepth)1001 static int32_t HcsTemplateVariablesDeclareGenWalk(ParserObject *current, int32_t walkDepth)
1002 {
1003 (void)walkDepth;
1004 if (current->objectBase.type == PARSEROP_CONFTERM && HcsGetTermType(current) == PARSEROP_ARRAY) {
1005 return HcsArrayVariablesDeclareGen(current);
1006 } else if (current->objectBase.type != PARSEROP_CONFNODE || current->configNode.nodeType != CONFIG_NODE_TEMPLATE) {
1007 return NOERR;
1008 }
1009
1010 if (!current->configNode.inheritCount) {
1011 return NOERR;
1012 }
1013 char writeBuffer[WRITE_BUFFER_LEN] = {'\0'};
1014 char nameBuff[OBJECT_NAME_MAX_LEN] = {'\0'};
1015 int32_t res = GenConfigStructName(current, nameBuff, OBJECT_NAME_MAX_LEN - 1);
1016 if (res) {
1017 return res;
1018 }
1019
1020 res = sprintf_s(writeBuffer, sizeof(writeBuffer), "static const struct %s ", nameBuff);
1021 PRINTF_CHECK_AND_RETURN(res);
1022 if (HcsGenTemplateVariableName(current, nameBuff, sizeof(nameBuff))) {
1023 return EOUTPUT;
1024 }
1025 res = sprintf_s(writeBuffer + strlen(writeBuffer), sizeof(writeBuffer) - strlen(writeBuffer), "%s[];\n", nameBuff);
1026 PRINTF_CHECK_AND_RETURN(res);
1027 return HcsOutputWrite(writeBuffer, strlen(writeBuffer));
1028 }
1029
HcsTemplateVariablesDeclareGen(ParserObject * astRoot)1030 static int32_t HcsTemplateVariablesDeclareGen(ParserObject *astRoot)
1031 {
1032 uint32_t writeCount = HcsGetOutputCurrentCount();
1033 if (HcsWalkAst(astRoot, AST_WALK_BACKEND, NULL, HcsTemplateVariablesDeclareGenWalk)) {
1034 return EOUTPUT;
1035 }
1036 if (writeCount == HcsGetOutputCurrentCount()) {
1037 /* if no template variable generated, should not output end line */
1038 return NOERR;
1039 }
1040 const char *lineEnd = "\n";
1041 return HcsOutputWrite(lineEnd, strlen(lineEnd));
1042 }
1043
HcsOutputTemplateImplement(ParserObject * astRoot)1044 static int32_t HcsOutputTemplateImplement(ParserObject *astRoot)
1045 {
1046 if (HcsTemplateVariablesDeclareGen(astRoot)) {
1047 return EOUTPUT;
1048 }
1049
1050 /* all template node will be global variables */
1051 return HcsWalkAst(astRoot, AST_WALK_BACKEND, NULL, HcsTemplateImplGenWalkCallBack);
1052 }
1053
HcsOutputCFile()1054 static int32_t HcsOutputCFile()
1055 {
1056 ParserObject *astRoot = HcsGetParserRoot();
1057 if (astRoot == NULL) {
1058 return EOUTPUT;
1059 }
1060
1061 if (HcsSymbolTableReset()) {
1062 return EOUTPUT;
1063 }
1064
1065 struct HcsFile *outputFIle = HcsOpenOutputFile(".c");
1066 if (outputFIle == NULL) {
1067 return EINVALF;
1068 }
1069
1070 if (HcsFormatOutputWrite(HCS_CONFIG_FILE_HEADER)) {
1071 HcsCloseOutput(outputFIle);
1072 return EOUTPUT;
1073 }
1074
1075 char *fileName = HcsGetOutputFileNameWithoutSuffix();
1076 if (fileName == NULL) {
1077 return EOUTPUT;
1078 }
1079 int32_t res = HcsFormatOutputWrite("#include \"%s.h\"\n\n", fileName);
1080 HcsMemFree(fileName);
1081 if (res != NOERR) {
1082 HcsCloseOutput(outputFIle);
1083 return EOUTPUT;
1084 }
1085
1086 res = HcsOutputTemplateImplement(astRoot);
1087 if (res != NOERR) {
1088 HcsCloseOutput(outputFIle);
1089 return EOUTPUT;
1090 }
1091
1092 /* Generate C global variables definition file */
1093 res = HcsWalkAst(astRoot, AST_WALK_ROUND, HcsImplementGenWalkCallBack, HcsImplementCloseBraceGen);
1094 if (res) {
1095 HcsCloseOutput(outputFIle);
1096 return res;
1097 }
1098
1099 res = HcsWriteFunctionImplement();
1100 HcsCloseOutput(outputFIle);
1101 return res;
1102 }
1103
HcsTextCodeOutput(void)1104 int32_t HcsTextCodeOutput(void)
1105 {
1106 int32_t ret = HcsSymbolTableInit();
1107 if (ret) {
1108 return ret;
1109 }
1110
1111 const char *symbolPrefix = HcsOptGetSymbolNamePrefix();
1112 if (symbolPrefix != NULL) {
1113 g_namePrefix = symbolPrefix;
1114 }
1115
1116 do {
1117 ret = InitConfigVariableNames();
1118 if (ret) {
1119 break;
1120 }
1121 ret = HcsOutputHeaderFile();
1122 if (ret) {
1123 break;
1124 }
1125
1126 ret = HcsOutputCFile();
1127 } while (false);
1128
1129 ReleaseConfigVariableNames();
1130 HcsSymbolTableRelease();
1131 return ret;
1132 }
1133