1 /*
2 * Copyright (c) 2020-2022 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(void)125 static void ReleaseConfigVariableNames(void)
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(void)143 static const char *GetConfigRootVariableName(void)
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(void)205 static void HcsSymbolTableRelease(void)
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 }
408 default:
409 break;
410 }
411
412 return res;
413 }
414
HcsObjectDefinitionGen(const ParserObject * current)415 static int32_t HcsObjectDefinitionGen(const ParserObject *current)
416 {
417 if (current->objectBase.type != PARSEROP_CONFNODE && current->objectBase.type != PARSEROP_CONFTERM) {
418 return NOERR;
419 }
420
421 int res = NOERR;
422 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("%*c", TAB_SIZE, ' '));
423 switch (current->objectBase.type) {
424 case PARSEROP_CONFNODE: {
425 char structName[OBJECT_NAME_MAX_LEN] = {'\0'};
426 res = GenConfigStructName(current, structName, OBJECT_NAME_MAX_LEN - 1);
427 if (res) {
428 return res;
429 }
430 if (current->configNode.nodeType == CONFIG_NODE_TEMPLATE) {
431 char nodeName[OBJECT_NAME_MAX_LEN] = {0};
432 if (strcpy_s(nodeName, sizeof(nodeName), current->configNode.name) != EOK) {
433 return EOUTPUT;
434 }
435 ToLowerCamelString(nodeName, strlen(nodeName));
436 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("const struct %s* %s;\n", structName, nodeName));
437 res = HcsFormatOutputWrite("%*cuint16_t %sSize;\n", TAB_SIZE, ' ', nodeName);
438 } else if (current->configNode.nodeType == CONFIG_NODE_INHERIT) {
439 return NOERR;
440 } else {
441 res = HcsFormatOutputWrite("struct %s %s;\n", structName, current->configNode.name);
442 }
443 break;
444 }
445 case PARSEROP_CONFTERM:
446 res = HcsPrintTermDefinition(current);
447 break;
448 default:
449 break;
450 }
451
452 return res;
453 }
454
HcsDuplicateCheckWalkCallBack(ParserObject * current,int32_t walkDepth)455 static int32_t HcsDuplicateCheckWalkCallBack(ParserObject *current, int32_t walkDepth)
456 {
457 (void)walkDepth;
458 if (current->objectBase.type != PARSEROP_CONFNODE || HcsIsInSubClassNode(current)) {
459 return NOERR;
460 }
461
462 return HcsSymbolTableAdd(current->objectBase.name, current);
463 }
464
HcsGenNormalNodeDefinition(ParserObject * object,int32_t walkDepth)465 static int32_t HcsGenNormalNodeDefinition(ParserObject *object, int32_t walkDepth)
466 {
467 (void)walkDepth;
468 char structName[OBJECT_NAME_MAX_LEN] = {'\0'};
469 int32_t res = GenConfigStructName(object, structName, OBJECT_NAME_MAX_LEN - 1);
470 if (res) {
471 return res;
472 }
473 if (HcsSymbolTableFind(structName)) {
474 return NOERR;
475 } else {
476 HcsSymbolTableAdd(structName, object);
477 }
478
479 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("struct %s {\n", structName));
480
481 ParserObject *terms = (ParserObject *)object->objectBase.child;
482 while (terms != NULL) {
483 res = HcsObjectDefinitionGen(terms);
484 if (res) {
485 return res;
486 }
487 terms = (ParserObject *)terms->objectBase.next;
488 }
489
490 return HcsFormatOutputWrite("};\n\n");
491 }
492
HcsGenNodeTemplateDefinition(ParserObject * object,int32_t walkDepth)493 static int32_t HcsGenNodeTemplateDefinition(ParserObject *object, int32_t walkDepth)
494 {
495 return HcsGenNormalNodeDefinition(object, walkDepth);
496 }
497
HcsDefinitionGenWalkCallBack(ParserObject * current,int32_t walkDepth)498 static int32_t HcsDefinitionGenWalkCallBack(ParserObject *current, int32_t walkDepth)
499 {
500 (void)walkDepth;
501 if (current->objectBase.type != PARSEROP_CONFNODE) {
502 return NOERR;
503 }
504 if (current->configNode.nodeType == CONFIG_NODE_TEMPLATE) {
505 return HcsGenNodeTemplateDefinition(current, walkDepth);
506 } else if (current->configNode.nodeType == CONFIG_NODE_INHERIT) {
507 return NOERR;
508 } else {
509 return HcsGenNormalNodeDefinition(current, walkDepth);
510 }
511 }
512
HcsPrintTermValue(const ParserObject * object)513 static uint32_t HcsPrintTermValue(const ParserObject *object)
514 {
515 int32_t res = NOERR;
516 switch (object->objectBase.type) {
517 case PARSEROP_UINT8: /* fallthrough */
518 case PARSEROP_UINT16: /* fallthrough */
519 case PARSEROP_UINT32: /* fallthrough */
520 case PARSEROP_UINT64:
521 res = HcsFormatOutputWrite("0x%" PRIx64, object->objectBase.integerValue);
522 break;
523 case PARSEROP_STRING:
524 res = HcsFormatOutputWrite("\"%s\"", object->objectBase.stringValue);
525 break;
526 default:
527 break;
528 }
529
530 return res;
531 }
532
533 #define MAX_CONFIG_TREE_DEPTH 100
HcsBuildObjectPath(const ParserObject * refObject)534 static char *HcsBuildObjectPath(const ParserObject *refObject)
535 {
536 const char *pathArray[MAX_CONFIG_TREE_DEPTH] = {0};
537 int32_t count = 0;
538 size_t pathStringLen = strlen(GetConfigRootVariableName()) + 1;
539 const ParserObject *it = refObject;
540
541 while (it != HcsGetParserRoot() && count < MAX_CONFIG_TREE_DEPTH) {
542 pathArray[count++] = it->objectBase.name;
543 pathStringLen += strlen(it->objectBase.name) + 1;
544 it = (ParserObject *)it->objectBase.parent;
545 }
546 if (count >= MAX_CONFIG_TREE_DEPTH) {
547 HCS_ERROR("reference a config node nested too deep over %u", MAX_CONFIG_TREE_DEPTH);
548 return NULL;
549 }
550
551 char *path = HcsMemZalloc(pathStringLen);
552 if (path == NULL) {
553 HCS_ERROR("%s:oom", __func__);
554 return NULL;
555 }
556
557 int32_t res = strcat_s(path, pathStringLen, GetConfigRootVariableName());
558 if (res) {
559 HcsMemFree(path);
560 HCS_ERROR("%s:string cat fail", __func__);
561 return NULL;
562 }
563
564 for (int32_t i = count - 1; i >= 0; --i) {
565 res = strcat_s(path, pathStringLen, ".");
566 if (res) {
567 HcsMemFree(path);
568 HCS_ERROR("%s:string cat fail", __func__);
569 return NULL;
570 }
571 res = strcat_s(path, pathStringLen, pathArray[i]);
572 if (res) {
573 HcsMemFree(path);
574 HCS_ERROR("%s:string cat fail", __func__);
575 return NULL;
576 }
577 }
578
579 return path;
580 }
581
HcsPrintArrayImplInSubClass(ParserObject * object,uint8_t tabSize)582 static int32_t HcsPrintArrayImplInSubClass(ParserObject *object, uint8_t tabSize)
583 {
584 char arrayName[VARIABLE_NAME_LEN] = {0};
585 if (GenConfigArrayName(object, arrayName, VARIABLE_NAME_LEN)) {
586 return EOUTPUT;
587 }
588 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite(".%s = %s,\n", object->objectBase.name, arrayName));
589 return HcsFormatOutputWrite("%*c.%sSize = %d,\n", tabSize, ' ',
590 object->configTerm.name, GetArraySize((ParserObject *)object->objectBase.child));
591 }
592
HcsPrintArrayContent(const ParserObject * object,int32_t tabSize)593 static int32_t HcsPrintArrayContent(const ParserObject *object, int32_t tabSize)
594 {
595 if (!GetArraySize(object)) {
596 return NOERR;
597 }
598
599 ParserObject *element = (ParserObject *)object->objectBase.child;
600 uint32_t elementCount = 0;
601 while (element != NULL) {
602 if (HcsPrintTermValue(element) != NOERR) {
603 return EOUTPUT;
604 }
605 if (elementCount++ >= ELEMENT_PER_LINE) {
606 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("\n%*c", tabSize, ' '));
607 }
608 element = (ParserObject *)element->configTerm.next;
609 if (element != NULL) {
610 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite(", "));
611 }
612 }
613
614 return NOERR;
615 }
616
HcsPrintArrayImplement(ParserObject * object,uint8_t tabSize)617 static int32_t HcsPrintArrayImplement(ParserObject *object, uint8_t tabSize)
618 {
619 if (HcsIsInSubClassNode(object)) {
620 return HcsPrintArrayImplInSubClass(object, tabSize);
621 }
622
623 ParserObject *termContext = (ParserObject *)object->objectBase.child;
624 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite(".%s = { ", object->configTerm.name));
625
626 if (HcsPrintArrayContent(termContext, tabSize + TAB_SIZE)) {
627 HCS_ERROR("fail to write array content");
628 return EOUTPUT;
629 }
630 return HcsFormatOutputWrite(" },\n");
631 }
632
HcsPrintTermImplement(ParserObject * object,int32_t tabSize)633 static int32_t HcsPrintTermImplement(ParserObject *object, int32_t tabSize)
634 {
635 int32_t res = NOERR;
636 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("%*c", tabSize, ' '));
637 ParserObject *termContext = (ParserObject *)object->objectBase.child;
638 switch (termContext->objectBase.type) {
639 case PARSEROP_UINT8:
640 /* fall-through */
641 case PARSEROP_UINT16:
642 /* fall-through */
643 case PARSEROP_UINT32:
644 /* fall-through */
645 case PARSEROP_UINT64:
646 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite(".%s = ", object->configTerm.name));
647 if (HcsPrintTermValue(termContext) != NOERR) {
648 return EOUTPUT;
649 }
650 res = HcsFormatOutputWrite(",\n");
651 break;
652 case PARSEROP_STRING:
653 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite(".%s = ", object->configTerm.name));
654 if (HcsPrintTermValue(termContext) != NOERR) {
655 return EOUTPUT;
656 }
657 res = HcsFormatOutputWrite(",\n");
658 break;
659 case PARSEROP_ARRAY:
660 res = HcsPrintArrayImplement(object, tabSize);
661 break;
662 case PARSEROP_NODEREF: {
663 char *refPath = HcsBuildObjectPath((ParserObject *)object->objectBase.child->value);
664 if (refPath == NULL) {
665 return EOUTPUT;
666 }
667 res = HcsFormatOutputWrite(".%s = &%s,\n", object->configTerm.name, refPath);
668 HcsMemFree(refPath);
669 break;
670 }
671 default:
672 break;
673 }
674
675 return res;
676 }
677
HcsGenTemplateVariableName(ParserObject * object,char * nameBuff,uint32_t nameBufferSize)678 static int32_t HcsGenTemplateVariableName(ParserObject *object, char *nameBuff, uint32_t nameBufferSize)
679 {
680 char tempName[OBJECT_NAME_MAX_LEN] = {'\0'};
681 if (strcpy_s(tempName, sizeof(tempName), object->objectBase.name) != EOK) {
682 HCS_ERROR("failed to copy string");
683 return EOUTPUT;
684 }
685 ToUpperCamelString(tempName, sizeof(tempName));
686 HcsSymbol *sym = HcsSymbolTableFind(object->objectBase.name);
687 if (sym == NULL) {
688 HcsSymbolTableAdd(object->objectBase.name, object);
689 } else if (sym->object != object && object->configNode.templateSignNum == 0) {
690 sym->duplicateCount++;
691 object->configNode.templateSignNum = sym->duplicateCount;
692 }
693
694 int32_t res;
695 if (object->configNode.templateSignNum) {
696 res = sprintf_s(nameBuff, nameBufferSize, "g_%s%s%u", g_littleHumpNamePrefix, tempName,
697 object->configNode.templateSignNum);
698 } else {
699 res = sprintf_s(nameBuff, nameBufferSize, "g_%s%s", g_littleHumpNamePrefix, tempName);
700 }
701
702 return (res > 0) ? NOERR : EFAIL;
703 }
704
HcsTemplateNodeImplGen(ParserObject * current,int32_t tabSize)705 static int32_t HcsTemplateNodeImplGen(ParserObject *current, int32_t tabSize)
706 {
707 char templateVariableName[VARIABLE_NAME_LEN] = {'\0'};
708 if (HcsGenTemplateVariableName(current, templateVariableName, sizeof(templateVariableName))) {
709 return EOUTPUT;
710 }
711 char nodeName[OBJECT_NAME_MAX_LEN] = {0};
712 if (strcpy_s(nodeName, sizeof(nodeName), current->configNode.name) != EOK) {
713 HCS_ERROR("%s: failed to copy string", __func__);
714 return EOUTPUT;
715 }
716
717 ToLowerCamelString(nodeName, strlen(nodeName));
718 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("%*c.%s = %s,\n", tabSize, ' ', nodeName,
719 current->configNode.inheritCount ? templateVariableName : "0"));
720
721 return HcsFormatOutputWrite("%*c.%sSize = %u,\n",
722 tabSize, ' ', nodeName, current->configNode.inheritCount);
723 }
724
HcsInheritObjectImplGen(ParserObject * current,int32_t tabSize)725 static int32_t HcsInheritObjectImplGen(ParserObject *current, int32_t tabSize)
726 {
727 if (current->configNode.nodeType == CONFIG_NODE_TEMPLATE) {
728 return HcsTemplateNodeImplGen(current, tabSize);
729 }
730
731 return NOERR;
732 }
733
HcsObjectImplementGen(ParserObject * current,int32_t tabSize)734 static int32_t HcsObjectImplementGen(ParserObject *current, int32_t tabSize)
735 {
736 int32_t res = NOERR;
737 switch (current->objectBase.type) {
738 case PARSEROP_CONFNODE:
739 if (current->configNode.nodeType != CONFIG_NODE_NOREF) {
740 res = HcsInheritObjectImplGen(current, tabSize);
741 return res ? res : EASTWALKBREAK;
742 }
743 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("%*c.%s = {\n", tabSize, ' ', current->configNode.name));
744 if (current->objectBase.child == NULL) {
745 res = HcsFormatOutputWrite("%*c},\n", tabSize, ' ');
746 }
747 break;
748 case PARSEROP_CONFTERM:
749 res = HcsPrintTermImplement(current, tabSize);
750 break;
751 default:
752 return NOERR;
753 }
754
755 return res;
756 }
757
HcsImplementGenWalkCallBack(ParserObject * current,int32_t walkDepth)758 static int32_t HcsImplementGenWalkCallBack(ParserObject *current, int32_t walkDepth)
759 {
760 if (current->objectBase.type != PARSEROP_CONFNODE && current->objectBase.type != PARSEROP_CONFTERM) {
761 return NOERR;
762 }
763
764 if (current->objectBase.type != PARSEROP_CONFNODE && HcsIsInSubClassNode(current)) {
765 return NOERR;
766 }
767
768 if (current == HcsGetParserRoot()) {
769 char structName[OBJECT_NAME_MAX_LEN] = {'\0'};
770 int32_t res = GenConfigStructName(current, structName, OBJECT_NAME_MAX_LEN - 1);
771 if (res) {
772 return res;
773 }
774 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("static const struct %s %s = {\n",
775 structName, GetConfigRootVariableName()));
776 if (current->objectBase.child == NULL) {
777 res = HcsFormatOutputWrite("};\n");
778 }
779 return res;
780 }
781 return HcsObjectImplementGen(current, walkDepth * TAB_SIZE);
782 }
783
HcsImplementCloseBraceGen(ParserObject * current,int32_t walkDepth)784 static int32_t HcsImplementCloseBraceGen(ParserObject *current, int32_t walkDepth)
785 {
786 if (current->objectBase.type != PARSEROP_CONFNODE) {
787 return NOERR;
788 }
789
790 if (current->configNode.nodeType == CONFIG_NODE_INHERIT) {
791 return NOERR;
792 }
793
794 int32_t tabSize = walkDepth * TAB_SIZE;
795
796 if (current != HcsGetParserRoot()) {
797 return HcsFormatOutputWrite("%*c},\n", tabSize, ' ');
798 } else {
799 return HcsFormatOutputWrite("};\n");
800 }
801 }
802
ToUpperString(char * str,uint32_t strLen)803 static void ToUpperString(char *str, uint32_t strLen)
804 {
805 for (uint32_t i = 0; i < strLen; ++i) {
806 str[i] = (char)toupper(str[i]);
807 }
808 }
809
810 #define HCS_HEADER_MACRO_MAX_LEN 150
GenHeaderProtectionMacro(void)811 static char *GenHeaderProtectionMacro(void)
812 {
813 char *fileName = HcsGetOutputFileNameWithoutSuffix();
814 if (fileName == NULL) {
815 return NULL;
816 }
817 ToUpperString(fileName, strlen(fileName));
818
819 char *macro = HcsMemZalloc(sizeof(char) * HCS_HEADER_MACRO_MAX_LEN);
820 if (macro == NULL) {
821 HCS_ERROR("oom");
822 HcsMemFree(fileName);
823 return NULL;
824 }
825
826 int32_t res = sprintf_s(macro, HCS_HEADER_MACRO_MAX_LEN, "HCS_CONFIG_%s_HEADER_H", fileName);
827 HcsMemFree(fileName);
828 if (res <= 0) {
829 HcsMemFree(macro);
830 return NULL;
831 }
832 return macro;
833 }
834
HcsWriteHeaderFileHead()835 static int32_t HcsWriteHeaderFileHead()
836 {
837 /* Write copyright info */
838 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite(HCS_CONFIG_FILE_HEADER));
839
840 /* Write header protection macro */
841 char *headerProtectMacro = GenHeaderProtectionMacro();
842 if (headerProtectMacro == NULL) {
843 return EOUTPUT;
844 }
845 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("#ifndef %s\n#define %s\n\n",
846 headerProtectMacro, headerProtectMacro));
847
848 /* Write include header file */
849 return HcsFormatOutputWrite(HCS_CONFIG_INCLUDE_HEADER);
850 }
851
HcsWriteHeaderFileEnd()852 static int32_t HcsWriteHeaderFileEnd()
853 {
854 /* Write header protection macro */
855 char *headerMacro = GenHeaderProtectionMacro();
856 if (headerMacro == NULL) {
857 return EOUTPUT;
858 }
859 int32_t ret = HcsFormatOutputWrite("\n\n#endif // %s", headerMacro);
860 HcsMemFree(headerMacro);
861
862 return ret;
863 }
864
HcsWriteFunctionDeclaration()865 static int32_t HcsWriteFunctionDeclaration()
866 {
867 return HcsFormatOutputWrite("const struct %s%sRoot* HdfGet%sModuleConfigRoot(void);", g_namePrefix,
868 g_bigHumpModuleName, g_bigHumpModuleName);
869 }
870
HcsWriteFunctionImplement()871 static int32_t HcsWriteFunctionImplement()
872 {
873 return HcsFormatOutputWrite(HCS_CONFIG_FUNC_IMPLEMENT, g_namePrefix,
874 g_bigHumpModuleName, g_bigHumpModuleName, GetConfigRootVariableName());
875 }
876
HcsOutputHeaderFile()877 static int32_t HcsOutputHeaderFile()
878 {
879 struct HcsFile *outputFIle = NULL;
880 ParserObject *astRoot = HcsGetParserRoot();
881 if (astRoot == NULL) {
882 return EOUTPUT;
883 }
884
885 /* Duplicate node name check */
886 if (HcsWalkAst(astRoot, AST_WALK_BACKEND, NULL, HcsDuplicateCheckWalkCallBack)) {
887 return EOUTPUT;
888 }
889
890 outputFIle = HcsOpenOutputFile(".h");
891 if (outputFIle == NULL) {
892 return EINVALF;
893 }
894
895 int32_t ret = HcsWriteHeaderFileHead();
896 if (ret) {
897 goto OUT;
898 }
899 /* Generate C header file containing the structure definition of config */
900 if (!HcsWalkAst(astRoot, AST_WALK_BACKEND, NULL, HcsDefinitionGenWalkCallBack)) {
901 ret = HcsWriteFunctionDeclaration();
902 if (ret) {
903 goto OUT;
904 }
905 }
906
907 ret = HcsWriteHeaderFileEnd();
908 OUT:
909 HcsCloseOutput(outputFIle);
910 return ret;
911 }
912
913
914 static int32_t g_baseTabsize = 0;
915
HcsTemplateObjectGenWalk(ParserObject * current,int32_t walkDepth)916 static int32_t HcsTemplateObjectGenWalk(ParserObject *current, int32_t walkDepth)
917 {
918 return HcsObjectImplementGen(current, walkDepth * TAB_SIZE + g_baseTabsize);
919 }
920
HcsTemplateCloseBraceGen(ParserObject * current,int32_t walkDepth)921 static int32_t HcsTemplateCloseBraceGen(ParserObject *current, int32_t walkDepth)
922 {
923 return HcsImplementCloseBraceGen(current, walkDepth + g_baseTabsize / TAB_SIZE);
924 }
925
HcsTemplateVariableGen(ParserObject * current)926 static int32_t HcsTemplateVariableGen(ParserObject *current)
927 {
928 ParserObject *child = (ParserObject *)current->objectBase.child;
929 while (child != NULL) {
930 int32_t res = HcsWalkAst(child, AST_WALK_ROUND, HcsTemplateObjectGenWalk, HcsTemplateCloseBraceGen);
931 if (res) {
932 return res;
933 }
934 child = (ParserObject *)child->objectBase.next;
935 }
936 return NOERR;
937 }
938
HcsTemplateImplGenWalkCallBack(ParserObject * current,int32_t walkDepth)939 static int32_t HcsTemplateImplGenWalkCallBack(ParserObject *current, int32_t walkDepth)
940 {
941 (void)walkDepth;
942 if (current->objectBase.type != PARSEROP_CONFNODE || current->configNode.nodeType != CONFIG_NODE_TEMPLATE) {
943 return NOERR;
944 }
945
946 if (!current->configNode.inheritCount) {
947 return NOERR;
948 }
949
950 char nameBuff[OBJECT_NAME_MAX_LEN] = {'\0'};
951 int32_t res = GenConfigStructName(current, nameBuff, OBJECT_NAME_MAX_LEN - 1);
952 if (res) {
953 return res;
954 }
955
956 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("static const struct %s ", nameBuff));
957 if (HcsGenTemplateVariableName(current, nameBuff, sizeof(nameBuff))) {
958 return EOUTPUT;
959 }
960 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("%s[] = {\n", nameBuff));
961
962 /* Generate C global variables definition file */
963 TemplateNodeInstance *subClasses = current->configNode.subClasses;
964 g_baseTabsize = TAB_SIZE + TAB_SIZE;
965 while (subClasses != NULL) {
966 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("%*c[%d] = {\n", TAB_SIZE, ' ',
967 subClasses->nodeObject->inheritIndex));
968
969 if (HcsTemplateVariableGen((ParserObject *)subClasses->nodeObject)) {
970 return EOUTPUT;
971 }
972 OUTPUT_CHECK_AND_RETURN(HcsFormatOutputWrite("%*c},\n", TAB_SIZE, ' '));
973 subClasses = subClasses->next;
974 }
975
976 return HcsFormatOutputWrite("};\n\n");
977 }
978
HcsArrayVariablesDeclareGen(ParserObject * term)979 static int32_t HcsArrayVariablesDeclareGen(ParserObject *term)
980 {
981 if (!HcsIsInSubClassNode(term)) {
982 return NOERR;
983 }
984
985 char nameBuff[OBJECT_NAME_MAX_LEN] = {'\0'};
986 int32_t res = GenConfigArrayName(term, nameBuff, OBJECT_NAME_MAX_LEN - 1);
987 if (res) {
988 return res;
989 }
990 ParserObject *array = (ParserObject *)term->configTerm.child;
991 res = HcsFormatOutputWrite("\nstatic const %s %s[%d] = {\n%*c", GetArrayType(array),
992 nameBuff, GetArraySize(array), TAB_SIZE, ' ');
993 OUTPUT_CHECK_AND_RETURN(res);
994
995 if (HcsPrintArrayContent(array, TAB_SIZE)) {
996 HCS_ERROR("fail to write array content");
997 return EOUTPUT;
998 }
999 return HcsFormatOutputWrite("\n};\n");
1000 }
1001
HcsTemplateVariablesDeclareGenWalk(ParserObject * current,int32_t walkDepth)1002 static int32_t HcsTemplateVariablesDeclareGenWalk(ParserObject *current, int32_t walkDepth)
1003 {
1004 (void)walkDepth;
1005 if (current->objectBase.type == PARSEROP_CONFTERM && HcsGetTermType(current) == PARSEROP_ARRAY) {
1006 return HcsArrayVariablesDeclareGen(current);
1007 } else if (current->objectBase.type != PARSEROP_CONFNODE || current->configNode.nodeType != CONFIG_NODE_TEMPLATE) {
1008 return NOERR;
1009 }
1010
1011 if (!current->configNode.inheritCount) {
1012 return NOERR;
1013 }
1014 char writeBuffer[WRITE_BUFFER_LEN] = {'\0'};
1015 char nameBuff[OBJECT_NAME_MAX_LEN] = {'\0'};
1016 int32_t res = GenConfigStructName(current, nameBuff, OBJECT_NAME_MAX_LEN - 1);
1017 if (res) {
1018 return res;
1019 }
1020
1021 res = sprintf_s(writeBuffer, sizeof(writeBuffer), "static const struct %s ", nameBuff);
1022 PRINTF_CHECK_AND_RETURN(res);
1023 if (HcsGenTemplateVariableName(current, nameBuff, sizeof(nameBuff))) {
1024 return EOUTPUT;
1025 }
1026 res = sprintf_s(writeBuffer + strlen(writeBuffer), sizeof(writeBuffer) - strlen(writeBuffer), "%s[];\n", nameBuff);
1027 PRINTF_CHECK_AND_RETURN(res);
1028 return HcsOutputWrite(writeBuffer, strlen(writeBuffer));
1029 }
1030
HcsTemplateVariablesDeclareGen(ParserObject * astRoot)1031 static int32_t HcsTemplateVariablesDeclareGen(ParserObject *astRoot)
1032 {
1033 uint32_t writeCount = HcsGetOutputCurrentCount();
1034 if (HcsWalkAst(astRoot, AST_WALK_BACKEND, NULL, HcsTemplateVariablesDeclareGenWalk)) {
1035 return EOUTPUT;
1036 }
1037 if (writeCount == HcsGetOutputCurrentCount()) {
1038 /* if no template variable generated, should not output end line */
1039 return NOERR;
1040 }
1041 const char *lineEnd = "\n";
1042 return HcsOutputWrite(lineEnd, strlen(lineEnd));
1043 }
1044
HcsOutputTemplateImplement(ParserObject * astRoot)1045 static int32_t HcsOutputTemplateImplement(ParserObject *astRoot)
1046 {
1047 if (HcsTemplateVariablesDeclareGen(astRoot)) {
1048 return EOUTPUT;
1049 }
1050
1051 /* all template node will be global variables */
1052 return HcsWalkAst(astRoot, AST_WALK_BACKEND, NULL, HcsTemplateImplGenWalkCallBack);
1053 }
1054
HcsOutputCFile()1055 static int32_t HcsOutputCFile()
1056 {
1057 ParserObject *astRoot = HcsGetParserRoot();
1058 if (astRoot == NULL) {
1059 return EOUTPUT;
1060 }
1061
1062 if (HcsSymbolTableReset()) {
1063 return EOUTPUT;
1064 }
1065
1066 struct HcsFile *outputFIle = HcsOpenOutputFile(".c");
1067 if (outputFIle == NULL) {
1068 return EINVALF;
1069 }
1070
1071 if (HcsFormatOutputWrite(HCS_CONFIG_FILE_HEADER)) {
1072 HcsCloseOutput(outputFIle);
1073 return EOUTPUT;
1074 }
1075
1076 char *fileName = HcsGetOutputFileNameWithoutSuffix();
1077 if (fileName == NULL) {
1078 return EOUTPUT;
1079 }
1080 int32_t res = HcsFormatOutputWrite("#include \"%s.h\"\n\n", fileName);
1081 HcsMemFree(fileName);
1082 if (res != NOERR) {
1083 HcsCloseOutput(outputFIle);
1084 return EOUTPUT;
1085 }
1086
1087 res = HcsOutputTemplateImplement(astRoot);
1088 if (res != NOERR) {
1089 HcsCloseOutput(outputFIle);
1090 return EOUTPUT;
1091 }
1092
1093 /* Generate C global variables definition file */
1094 res = HcsWalkAst(astRoot, AST_WALK_ROUND, HcsImplementGenWalkCallBack, HcsImplementCloseBraceGen);
1095 if (res) {
1096 HcsCloseOutput(outputFIle);
1097 return res;
1098 }
1099
1100 res = HcsWriteFunctionImplement();
1101 HcsCloseOutput(outputFIle);
1102 return res;
1103 }
1104
HcsTextCodeOutput(void)1105 int32_t HcsTextCodeOutput(void)
1106 {
1107 int32_t ret = HcsSymbolTableInit();
1108 if (ret) {
1109 return ret;
1110 }
1111
1112 const char *symbolPrefix = HcsOptGetSymbolNamePrefix();
1113 if (symbolPrefix != NULL) {
1114 g_namePrefix = symbolPrefix;
1115 }
1116
1117 do {
1118 ret = InitConfigVariableNames();
1119 if (ret) {
1120 break;
1121 }
1122 ret = HcsOutputHeaderFile();
1123 if (ret) {
1124 break;
1125 }
1126
1127 ret = HcsOutputCFile();
1128 } while (false);
1129
1130 ReleaseConfigVariableNames();
1131 HcsSymbolTableRelease();
1132 return ret;
1133 }
1134