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