• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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