• 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 "hcs_ast.h"
10 #include <string.h>
11 #include <securec.h>
12 #include "hcs_file.h"
13 #include "hcs_mem.h"
14 #include "hcs_log.h"
15 #include "hcs_option.h"
16 
17 #define ANONYMOUS_OBJECT_NAME "|_"
18 static ParserObject *g_parserRoot = NULL;
19 
HcsIsAnonymousObject(const ParserObject * obj)20 bool HcsIsAnonymousObject(const ParserObject *obj)
21 {
22     return strcmp(obj->objectBase.name, ANONYMOUS_OBJECT_NAME) == 0;
23 }
24 
HcsAllocParserObject(void)25 ParserObject *HcsAllocParserObject(void)
26 {
27     ParserObject *newObject = (ParserObject *)HcsMemZalloc(sizeof(ParserObject));
28     if (newObject == NULL) {
29         HCS_ERROR("%s:%d OOM", __func__, __LINE__);
30         return NULL;
31     }
32     newObject->objectBase.src = HcsGetCurrentSourceName();
33     newObject->objectBase.lineno = HcsGetCurrentSourceLine();
34     return newObject;
35 }
36 
HcsAstFreeObject(ParserObject * object)37 void HcsAstFreeObject(ParserObject *object)
38 {
39     if (object == NULL) {
40         return;
41     }
42     if (object->objectBase.type == PARSEROP_CONFNODE) {
43         TemplateNodeInstance *subClass = object->configNode.subClasses;
44         while (subClass != NULL) {
45             TemplateNodeInstance *temp = subClass;
46             subClass = subClass->next;
47             HcsMemFree(temp);
48         }
49         HcsMemFree((char *)object->configNode.refNodePath);
50     }
51 
52     HcsAstRemoveChildLink(object->objectBase.parent, (ParserObjectBase *)object);
53     if (object->objectBase.type == PARSEROP_STRING) {
54         HcsMemFree(object->objectBase.stringValue);
55     }
56 
57     HcsMemFree((char*)object->objectBase.name);
58     HcsMemFree(object);
59 }
60 
HcsAstWalkFreeObjectCallback(ParserObject * object,int32_t walkDepth)61 static int32_t HcsAstWalkFreeObjectCallback(ParserObject *object, int32_t walkDepth)
62 {
63     (void)walkDepth;
64     HcsAstFreeObject(object);
65     return NOERR;
66 }
67 
HcsAstFreeObjectAndSubtree(ParserObject * object)68 static void HcsAstFreeObjectAndSubtree(ParserObject *object)
69 {
70     if (HcsWalkAst(object, AST_WALK_BACKEND, NULL, HcsAstWalkFreeObjectCallback)) {
71         HCS_WARNING("%s may failed", __func__);
72     }
73 }
74 
HcsDeleteParserObjectTree(ParserObject * object)75 void HcsDeleteParserObjectTree(ParserObject *object)
76 {
77     if (object == NULL) {
78         return;
79     }
80     /* delete current tree and subtree */
81     HcsAstFreeObjectAndSubtree(object);
82 }
83 
HcsGetParserRoot(void)84 ParserObject *HcsGetParserRoot(void)
85 {
86     if (g_parserRoot != NULL) {
87         return g_parserRoot;
88     }
89     HCS_DEBUG("instance root node");
90     char *rootNodeName = strdup("root");
91     if (rootNodeName == NULL) {
92         HCS_ERROR("%s:%d OOM", __func__, __LINE__);
93         return NULL;
94     }
95     g_parserRoot = HcsNewConfigNode(rootNodeName, CONFIG_NODE_NOREF, NULL);
96     if (g_parserRoot == NULL) {
97         HcsMemFree(rootNodeName);
98     }
99     return g_parserRoot;
100 }
101 
HcsSetParserRoot(ParserObject * newRoot)102 void HcsSetParserRoot(ParserObject *newRoot)
103 {
104     g_parserRoot = newRoot;
105 }
106 
HcsNewConfigNode(const char * nodeName,uint32_t nodeType,const char * refName)107 ParserObject *HcsNewConfigNode(const char *nodeName, uint32_t nodeType, const char *refName)
108 {
109     HCS_DEBUG("create node: %s", nodeName ? nodeName : "nil");
110     ParserObject *object = HcsAllocParserObject();
111     if (object == NULL) {
112         return NULL;
113     }
114     object->configNode.name = nodeName;
115     object->objectBase.type = PARSEROP_CONFNODE;
116     if (nodeType) {
117         object->configNode.nodeType = nodeType;
118         object->configNode.refNodePath = refName;
119     }
120 
121     return object;
122 }
123 
HcsFitIntegerValueType(uint64_t value)124 uint32_t HcsFitIntegerValueType(uint64_t value)
125 {
126     if (value <= UINT8_MAX) {
127         return PARSEROP_UINT8;
128     } else if (value <= UINT16_MAX) {
129         return PARSEROP_UINT16;
130     } else if (value <= UINT32_MAX) {
131         return PARSEROP_UINT32;
132     } else {
133         return PARSEROP_UINT64;
134     }
135 }
136 
HcsNewConfigTerm(const char * name,ParserObject * value)137 ParserObject *HcsNewConfigTerm(const char *name, ParserObject *value)
138 {
139     if (name == NULL || value == NULL) {
140         return NULL;
141     }
142     ParserObject *object = HcsAllocParserObject();
143     if (object == NULL) {
144         return NULL;
145     }
146     object->objectBase.name = name;
147     object->objectBase.type = PARSEROP_CONFTERM;
148     object->objectBase.child = (ParserObjectBase *)value;
149     ParserObjectBase *child = &value->objectBase;
150     while (child != NULL) {
151         child->parent = (ParserObjectBase *)object;
152         child = child->next;
153     }
154 
155     return object;
156 }
157 
HcsNewParserObject(const char * name,uint32_t type,uint64_t value)158 ParserObject *HcsNewParserObject(const char *name, uint32_t type, uint64_t value)
159 {
160     if (type >= PARSEROP_COUNT) {
161         HCS_ERROR("unknown object type");
162         return NULL;
163     }
164 
165     ParserObject *object = HcsAllocParserObject();
166     if (object == NULL) {
167         return NULL;
168     }
169 
170     if (name == NULL) {
171         name = strdup(ANONYMOUS_OBJECT_NAME);
172         if (name == NULL) {
173             HcsMemFree(object);
174             return NULL;
175         }
176     }
177 
178     object->objectBase.name = name;
179     object->objectBase.type = type;
180     object->objectBase.value = value;
181 
182     switch (type) {
183         case PARSEROP_UINT8:  /* fall-through */
184         case PARSEROP_UINT16: /* fall-through */
185         case PARSEROP_UINT32: /* fall-through */
186         case PARSEROP_UINT64:
187             object->objectBase.type = HcsFitIntegerValueType(value);
188             break;
189         default:
190             break;
191     }
192 
193     return object;
194 }
195 
HcsAstAddChild(ParserObject * parent,ParserObject * child)196 ParserObject *HcsAstAddChild(ParserObject *parent, ParserObject *child)
197 {
198     if (child == NULL) {
199         return parent;
200     }
201 
202     if (parent->objectBase.child == NULL) {
203         parent->objectBase.child = (ParserObjectBase *)child;
204         ParserObjectBase *childNext = &child->objectBase;
205         while (childNext != NULL) {
206             childNext->parent = (ParserObjectBase *)parent;
207             childNext = childNext->next;
208         }
209     } else {
210         HcsAstAddPeer((ParserObject *)parent->configNode.child, child);
211     }
212 
213     return parent;
214 }
215 
HcsAstRemoveChildLink(ParserObjectBase * parent,ParserObjectBase * child)216 void HcsAstRemoveChildLink(ParserObjectBase *parent, ParserObjectBase *child)
217 {
218     if (parent == NULL || child == NULL || child->parent != parent) {
219         return;
220     }
221     child->parent = NULL;
222     if (parent->child == child) {
223         parent->child = child->next;
224         child->next = NULL;
225         return;
226     }
227 
228     ParserObjectBase *pre = parent->child;
229     while (pre != NULL) {
230         if (pre->next == child) {
231             pre->next = pre->next->next;
232             break;
233         }
234 
235         pre = pre->next;
236     }
237     child->next = NULL;
238 }
239 
HcsAstAddPeer(ParserObject * forward,ParserObject * peer)240 ParserObject *HcsAstAddPeer(ParserObject *forward, ParserObject *peer)
241 {
242     if (forward == NULL && peer == NULL) {
243         return forward;
244     }
245 
246     if (forward == NULL) {
247         return peer;
248     }
249 
250     if (peer == NULL) {
251         return forward;
252     }
253 
254     if (forward == peer) {
255         HCS_ERROR("add self as peer");
256         return NULL;
257     }
258 
259     ParserObjectBase *lastNode = &forward->objectBase;
260     while (lastNode->next) {
261         lastNode = lastNode->next;
262     }
263 
264     lastNode->next = (ParserObjectBase *)peer;
265     peer->objectBase.parent = forward->objectBase.parent;
266 
267     ParserObjectBase *peerNext = peer->objectBase.next;
268     while (peerNext != NULL) {
269         peerNext->parent = forward->objectBase.parent;
270         peerNext = peerNext->next;
271     }
272 
273     return forward;
274 }
275 
HcsAstLookupObjectInPeers(const ParserObject * current,const char * name)276 ParserObject *HcsAstLookupObjectInPeers(const ParserObject *current, const char *name)
277 {
278     ParserObject *peer = (ParserObject *)current->objectBase.parent->child;
279     while (peer != NULL) {
280         if (peer->objectBase.type == PARSEROP_CONFNODE && !strcmp(peer->objectBase.name, name)) {
281             return peer;
282         }
283 
284         peer = (ParserObject *)peer->objectBase.next;
285     }
286 
287     return NULL;
288 }
289 
HcsAstLookupObjectInChildren(const ParserObject * current,const char * name)290 ParserObject *HcsAstLookupObjectInChildren(const ParserObject *current, const char *name)
291 {
292     if (current == NULL) {
293         return NULL;
294     }
295     ParserObject *peer = (ParserObject *)current->objectBase.child;
296     while (peer != NULL) {
297         if (!strcmp(peer->objectBase.name, name)) {
298             return peer;
299         }
300 
301         peer = (ParserObject *)peer->objectBase.next;
302     }
303 
304     return NULL;
305 }
306 
HcsParserObjectClone(const ParserObject * object)307 static ParserObject *HcsParserObjectClone(const ParserObject *object)
308 {
309     if (object == NULL) {
310         return NULL;
311     }
312     ParserObject *clone = HcsAllocParserObject();
313     if (clone == NULL) {
314         HCS_ERROR("%s:%d OOM", __func__, __LINE__);
315         return NULL;
316     }
317 
318     (void)memcpy_s(clone, sizeof(*clone), object, sizeof(*object));
319     clone->configNode.refNodePath = NULL;
320     clone->objectBase.name = NULL;
321     clone->objectBase.child = NULL;
322     clone->objectBase.next = NULL;
323     clone->objectBase.parent = NULL;
324     if (object->objectBase.type == PARSEROP_STRING) {
325         clone->objectBase.stringValue = strdup(object->objectBase.stringValue);
326         if (clone->objectBase.stringValue == NULL) {
327             HcsAstFreeObject(clone);
328             return NULL;
329         }
330     }
331     if (object->configNode.refNodePath != NULL) {
332         clone->configNode.refNodePath = strdup(object->configNode.refNodePath);
333         if (clone->configNode.refNodePath == NULL) {
334             HcsAstFreeObject(clone);
335             return NULL;
336         }
337     }
338     clone->objectBase.name = strdup(object->objectBase.name);
339     if (clone->objectBase.name == NULL) {
340         HcsAstFreeObject(clone);
341         return NULL;
342     }
343 
344     return clone;
345 }
346 
HcsAstFreeSubTree(ParserObject * object)347 void HcsAstFreeSubTree(ParserObject *object)
348 {
349     ParserObjectBase *child = object->objectBase.child;
350     while (child != NULL) {
351         ParserObjectBase *tmp = child->next;
352         HcsAstRemoveChildLink((ParserObjectBase *)object, child);
353         HcsAstFreeObjectAndSubtree((ParserObject *)child);
354         child = tmp;
355     }
356 }
357 
HcsIsEmptyArray(const ParserObject * src)358 bool HcsIsEmptyArray(const ParserObject *src)
359 {
360     return src->objectBase.child == NULL;
361 }
362 
HcsAstCopyArray(const ParserObject * src,ParserObject * dst)363 int32_t HcsAstCopyArray(const ParserObject *src, ParserObject *dst)
364 {
365     if (src == NULL || dst == NULL) {
366         return NOERR;
367     }
368 
369     if (HcsIsEmptyArray(src)) {
370         return NOERR;
371     }
372 
373     if (!HcsIsEmptyArray(dst) &&
374         !HcsIsSameTypeObject((ParserObject *)src->objectBase.child, (ParserObject *)dst->objectBase.child)) {
375         HCS_OBJECT_ERROR(dst, "overwrite different type");
376         return EINVALARG;
377     }
378 
379     /* Children of array is anonymous object, can not use name to index them, delete first */
380     HcsAstFreeSubTree(dst);
381     dst->objectBase.child = NULL;
382 
383     ParserObject *arrayElement = (ParserObject *)src->objectBase.child;
384     while (arrayElement != NULL) {
385         ParserObject *copy = HcsParserObjectClone(arrayElement);
386         if (copy == NULL) {
387             HCS_ERROR("%s:%d OOM", __func__, __LINE__);
388             return EOOM;
389         }
390         HcsAstAddChild(dst, copy);
391         arrayElement = (ParserObject *)arrayElement->objectBase.next;
392     }
393 
394     return NOERR;
395 }
396 
HcsCopyObject(const ParserObject * src,ParserObject * dst)397 static int32_t HcsCopyObject(const ParserObject *src, ParserObject *dst)
398 {
399     if (!HcsIsSameTypeObject(src, dst)) {
400         HCS_OBJECT_ERROR(src, "overwrite different type");
401         return EINVALARG;
402     }
403 
404     if (HcsIsNumberObject(src)) {
405         dst->objectBase.integerValue = src->objectBase.integerValue;
406     } else if (HcsIsStringObject(src)) {
407         HcsMemFree(dst->objectBase.stringValue);
408         dst->objectBase.stringValue = strdup(src->objectBase.stringValue);
409         if (dst->objectBase.stringValue == NULL) {
410             HCS_ERROR("%s:%d OOM", __func__, __LINE__);
411             return EOOM;
412         }
413     } else if (src->objectBase.type == PARSEROP_ARRAY) {
414         return HcsAstCopyArray(src, dst);
415     }
416 
417     return NOERR;
418 }
419 
420 /*
421  * Copy src tree as dstTree's child
422  */
HcsAstCopyTree(ParserObject * src,ParserObject * dstTree,uint32_t overWriteFlag)423 static int32_t HcsAstCopyTree(ParserObject *src, ParserObject *dstTree, uint32_t overWriteFlag)
424 {
425     if (src == NULL || dstTree == NULL) {
426         return NOERR;
427     }
428 
429     int32_t ret;
430     ParserObject *dstExistObject = HcsAstLookupObjectInChildren(dstTree, src->objectBase.name);
431     if (dstExistObject == NULL) {
432         ParserObject *copy = HcsParserObjectClone(src);
433         HcsAstAddChild(dstTree, copy);
434         dstExistObject = copy;
435         if (src->objectBase.type == PARSEROP_ARRAY) {
436             return HcsAstCopyArray(src, dstExistObject);
437         }
438     } else if (overWriteFlag == AST_COPY_SRC_OVER_DST) {
439         ret = HcsCopyObject(src, dstExistObject);
440         if (ret || src->objectBase.type == PARSEROP_ARRAY) {
441             return ret;
442         }
443     } else if (HcsOptShouldGenTextConfig() && HcsIsNumberObject(src) &&
444         dstExistObject->objectBase.type > src->objectBase.type) {
445         src->objectBase.type = dstExistObject->objectBase.type;
446     }
447 
448     ParserObjectBase *srcChild = src->objectBase.child;
449     while (srcChild != NULL) {
450         ret = HcsAstCopyTree((ParserObject *)srcChild, dstExistObject, overWriteFlag);
451         if (ret) {
452             return ret;
453         }
454         srcChild = srcChild->next;
455     }
456 
457     return NOERR;
458 }
459 
HcsAstCopySubTree(ParserObject * src,ParserObject * dst,uint32_t overWriteFlag)460 int32_t HcsAstCopySubTree(ParserObject *src, ParserObject *dst, uint32_t overWriteFlag)
461 {
462     if (src == NULL || dst == NULL) {
463         return NOERR;
464     }
465 
466     if (!HcsIsSameTypeObject(src, dst)) {
467         HCS_OBJECT_ERROR(src, "overwrite different type");
468         return EINVALARG;
469     }
470 
471     ParserObjectBase *srcChild = src->objectBase.child;
472     while (srcChild != NULL) {
473         int32_t ret = HcsAstCopyTree((ParserObject *)srcChild, dst, overWriteFlag);
474         if (ret) {
475             return ret;
476         }
477         srcChild = srcChild->next;
478     }
479 
480     return NOERR;
481 }
482 
AstWalkCallBackDefault(ParserObject * current,int32_t walkDepth)483 static int32_t inline AstWalkCallBackDefault(ParserObject *current, int32_t walkDepth)
484 {
485     (void)current;
486     (void)walkDepth;
487     return NOERR;
488 }
489 
HcsForwardWalkAst(ParserObject * start,AstWalkCallBack callback)490 static int32_t HcsForwardWalkAst(ParserObject *start, AstWalkCallBack callback)
491 {
492     ParserObjectBase *startObj = (ParserObjectBase *)start;
493     ParserObjectBase *forwardWalkObj = startObj;
494     int32_t walkDepth = 0;
495     bool preVisited = false;
496 
497     while (forwardWalkObj != NULL) {
498         if (!preVisited) {
499             int32_t ret = callback((ParserObject *)forwardWalkObj, walkDepth);
500             if (ret && ret != EASTWALKBREAK) {
501                 return EINVALARG;
502             } else if (!ret && forwardWalkObj->child) {
503                 /* when callback return EASTWALKBREAK, not walk current's child */
504                 walkDepth++;
505                 forwardWalkObj = forwardWalkObj->child;
506                 continue;
507             }
508         }
509         if (forwardWalkObj == startObj) {
510             break;
511         }
512 
513         if (forwardWalkObj->next) {
514             forwardWalkObj = forwardWalkObj->next;
515             preVisited = false;
516         } else {
517             forwardWalkObj = forwardWalkObj->parent;
518             preVisited = true;
519             walkDepth--;
520         }
521     }
522 
523     return NOERR;
524 }
525 
HcsBackwardWalkAst(ParserObject * start,AstWalkCallBack callback)526 static int32_t HcsBackwardWalkAst(ParserObject *start, AstWalkCallBack callback)
527 {
528     ParserObjectBase *startObj = (ParserObjectBase *)start;
529     ParserObjectBase *backWalkObj = startObj;
530     ParserObjectBase *next = NULL;
531     ParserObjectBase *parent = NULL;
532     int32_t walkDepth = 0;
533     bool preVisited = false;
534 
535     while (backWalkObj != NULL) {
536         if (backWalkObj->child == NULL || preVisited) {
537             next = backWalkObj->next;
538             parent = backWalkObj->parent;
539             /* can safe delete current in callback */
540             if (callback((ParserObject *)backWalkObj, walkDepth)) {
541                 return EINVALARG;
542             }
543         } else {
544             if (backWalkObj->child) {
545                 walkDepth++;
546                 backWalkObj = backWalkObj->child;
547                 continue;
548             }
549         }
550         if (backWalkObj == startObj) {
551             break;
552         }
553 
554         if (next != NULL) {
555             backWalkObj = next;
556             preVisited = false;
557         } else {
558             backWalkObj = parent;
559             preVisited = true;
560             walkDepth--;
561         }
562     }
563 
564     return NOERR;
565 }
566 
HcsRoundWalkAst(ParserObject * start,AstWalkCallBack forwardCallback,AstWalkCallBack backwardCallback)567 static int32_t HcsRoundWalkAst(ParserObject *start, AstWalkCallBack forwardCallback, AstWalkCallBack backwardCallback)
568 {
569     ParserObjectBase *startObj = (ParserObjectBase *)start;
570     ParserObjectBase *roundWalkObj = startObj;
571     int32_t walkDepth = 0;
572     bool preVisited = false;
573 
574     while (roundWalkObj != NULL) {
575         if (preVisited) {
576             if (backwardCallback((ParserObject *)roundWalkObj, walkDepth)) {
577                 return EFAIL;
578             }
579         } else {
580             int32_t ret = forwardCallback((ParserObject *)roundWalkObj, walkDepth);
581             /* when callback return EASTWALKBREAK, not walk current's child */
582             if (ret && ret != EASTWALKBREAK) {
583                 return EFAIL;
584             } else if (!ret && roundWalkObj->child) {
585                 walkDepth++;
586                 roundWalkObj = roundWalkObj->child;
587                 continue;
588             }
589         }
590         if (roundWalkObj == startObj) {
591             break;
592         }
593 
594         if (roundWalkObj->next) {
595             roundWalkObj = roundWalkObj->next;
596             preVisited = false;
597         } else {
598             roundWalkObj = roundWalkObj->parent;
599             preVisited = true;
600             walkDepth--;
601         }
602     }
603 
604     return NOERR;
605 }
606 
HcsGetTermType(ParserObject * object)607 uint16_t HcsGetTermType(ParserObject *object)
608 {
609     if (object->objectBase.type != PARSEROP_CONFTERM || object->objectBase.child == NULL) {
610         return 0;
611     }
612     return object->objectBase.child->type;
613 }
614 
HcsWalkAst(ParserObject * start,uint32_t walkDirection,AstWalkCallBack forwardCallback,AstWalkCallBack backwardCallback)615 int32_t HcsWalkAst(ParserObject *start, uint32_t walkDirection, AstWalkCallBack forwardCallback,
616     AstWalkCallBack backwardCallback)
617 {
618     forwardCallback = forwardCallback ? forwardCallback : AstWalkCallBackDefault;
619     backwardCallback = backwardCallback ? backwardCallback : AstWalkCallBackDefault;
620     ParserObject *startObj = start ? start : g_parserRoot;
621 
622     int32_t ret = EFAIL;
623     switch (walkDirection) {
624         case AST_WALK_FORWARD:
625             ret = HcsForwardWalkAst(startObj, forwardCallback);
626             break;
627         case AST_WALK_BACKEND:
628             ret = HcsBackwardWalkAst(startObj, backwardCallback);
629             break;
630         case AST_WALK_ROUND:
631             ret = HcsRoundWalkAst(startObj, forwardCallback, backwardCallback);
632             break;
633         default:
634             HCS_ERROR("unknown ast walk type(%u)", walkDirection);
635             return EINVALARG;
636     }
637 
638     return ret;
639 }
640 
641 static const char *g_parserOpTypeStr[PARSEROP_COUNT] = {
642     [PARSEROP_UINT8] = "UINT8",
643     [PARSEROP_UINT16] = "UINT16",
644     [PARSEROP_UINT32] = "UINT32",
645     [PARSEROP_UINT64] = "UINT64",
646     [PARSEROP_STRING] = "STRING",
647     [PARSEROP_CONFNODE] = "CONFNODE",
648     [PARSEROP_CONFTERM] = "CONFTERM",
649     [PARSEROP_ARRAY] = "ARRAY",
650     [PARSEROP_NODEREF] = "NODEREF",
651 };
652 
ParserOpTypeToStr(uint32_t type)653 static const char *ParserOpTypeToStr(uint32_t type)
654 {
655     if (type >= PARSEROP_COUNT) {
656         return "unknown_type";
657     }
658 
659     return g_parserOpTypeStr[type];
660 }
661 
662 #define AST_PRINT_TAB_SIZE 2
663 
AstDumpWalkCallback(ParserObject * current,int32_t walkDepth)664 static int32_t AstDumpWalkCallback(ParserObject *current, int32_t walkDepth)
665 {
666     int32_t printTab = walkDepth * AST_PRINT_TAB_SIZE;
667 
668     HCS_PRINT("%-15s%*c%-10s", ParserOpTypeToStr(current->objectBase.type), printTab, ' ', current->configNode.name);
669     switch (current->objectBase.type) {
670         case PARSEROP_UINT8:
671         case PARSEROP_UINT16:
672         case PARSEROP_UINT32:
673         case PARSEROP_UINT64:
674             HCS_PRINT(" %"PRIx64, current->configTerm.integerValue);
675             break;
676         case PARSEROP_STRING:
677             HCS_PRINT(" %s", current->configTerm.stringValue);
678             break;
679         case PARSEROP_CONFNODE:
680             if (current->configNode.nodeType != CONFIG_NODE_NOREF) {
681                 HCS_PRINT("%-10s %-10s", HcsParserNodeTypeToStr(current->configNode.nodeType),
682                     current->configNode.refNodePath ? current->configNode.refNodePath : "");
683             }
684             break;
685         case PARSEROP_NODEREF:
686             HCS_PRINT("%-10s %"PRIx64, "NodeReference", current->objectBase.value);
687             break;
688         default:
689             break;
690     }
691 
692     HCS_PRINT("\n");
693 
694     return NOERR;
695 }
696 
HcsCountArraySize(const ParserObject * arrayObj)697 uint16_t HcsCountArraySize(const ParserObject *arrayObj)
698 {
699     if (arrayObj == NULL) {
700         return 0;
701     }
702 
703     ParserObjectBase *child = arrayObj->objectBase.child;
704     uint16_t size = 0;
705     while (child != NULL) {
706         size++;
707         child = child->next;
708     }
709 
710     return size;
711 }
712 
HcsGetModuleName(void)713 const char *HcsGetModuleName(void)
714 {
715     ParserObject *root = HcsGetParserRoot();
716     if (root == NULL) {
717         return NULL;
718     }
719 
720     ParserObject *moduleAttr = HcsAstLookupObjectInChildren(root, "module");
721     if (moduleAttr == NULL) {
722         HCS_OBJECT_ERROR(root, "miss 'module' attribute under root node");
723         return NULL;
724     }
725 
726     return moduleAttr->configTerm.child->stringValue;
727 }
728 
HcsDumpAst(const char * label)729 void HcsDumpAst(const char *label)
730 {
731     HCS_PRINT("\nDump %s AST tree:\n", label);
732     if (HcsWalkAst(g_parserRoot, AST_WALK_FORWARD, AstDumpWalkCallback, NULL)) {
733         HCS_WARNING("%s failed", __func__);
734     }
735 }