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 }