• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# Copyright (c) 2021-2023 Huawei Device Co., Ltd.
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16import sys
17import os
18import json
19import argparse
20from collections import Counter
21
22sys.path.append(
23    os.path.dirname(
24        os.path.dirname(
25            os.path.dirname(os.path.dirname(os.path.abspath(__file__))))))
26
27from third_party.PyYAML.lib import yaml  # noqa: E402
28
29_DUPLICATE_KEY_DEF = "duplicate key definition"
30_EMPTY_YAML = "empty yaml file input"
31_INVALID_YAML = "invalid yaml format"
32_DUPLICATE_DOMAIN = "duplicate domain"
33_INVALID_DOMAIN_NUMBER = "invalid domain number"
34_INVALID_DOMAIN_LENGTH = "invalid domain length"
35_INVALID_DOMAIN_CHAR = "invalid domain character"
36_INVALID_DOMAIN_CHAR_HEAD = "invalid domain character head"
37_INVALID_EVENT_NUMBER = "invalid event number"
38_INVALID_EVENT_LENGTH = "invalid event length"
39_INVALID_EVENT_CHAR = "invalid event character"
40_INVALID_EVENT_CHAR_HEAD = "invalid event character head"
41_MISSING_EVENT_BASE = "missing event base"
42_MISSING_EVENT_TYPE = "missing event type"
43_INVALID_EVENT_TYPE = "invalid event type"
44_MISSING_EVENT_LEVEL = "missing event level"
45_INVALID_EVENT_LEVEL = "invalid event level"
46_MISSING_EVENT_DESC = "missing event desc"
47_INVALID_EVENT_DESC_LENGTH = "invalid event desc length"
48_INVALID_EVENT_TAG_NUM = "invalid event tag number"
49_INVALID_EVENT_TAG_LEN = "invalid event tag length"
50_INVALID_EVENT_TAG_CHAR = "invalid event tag character"
51_DUPLICATE_EVENT_TAG = "duplicate event tag"
52_INVALID_EVENT_BASE_KEY = "invalid event base key"
53_INVALID_EVENT_PARAM_NUM = "invalid event param number"
54_INVALID_EVENT_PARAM_LEN = "invalid event param length"
55_INVALID_EVENT_PARAM_CHAR = "invalid event param character"
56_INVALID_EVENT_PARAM_CHAR_HEAD = "invalid event param character head"
57_MISSING_EVENT_PARAM_TYPE = "missing event param type"
58_INVALID_EVENT_PARAM_TYPE = "invalid event param type"
59_INVALID_EVENT_PARAM_ARRSIZE = "invalid event param arrsize"
60_MISSING_EVENT_PARAM_DESC = "missing event param desc"
61_INVALID_EVENT_PARAM_DESC_LEN = "invalid event param desc length"
62_INVALID_EVENT_PARAM_KEY = "invalid event param key"
63_DEPRECATED_EVENT_NAME_PREFIX = "deprecated event name prefix"
64_DEPRECATED_PARAM_NAME_PREFIX = "deprecated param name prefix"
65_DEPRECATED_TAG_NAME = "deprecated tag name"
66_DEPRECATED_EVENT_DESC_NAME = "deprecated event desc name"
67_DEPRECATED_PARAM_DESC_NAME = "deprecated param desc name"
68_INVALID_DOMAIN_DEF = "invalid definition type for domain"
69_INVALID_EVENT_DEF = "invalid definition type for event"
70_INVALID_EVENT_BASE_DEF = "invalid definition type for event base"
71_INVALID_EVENT_TYPE_DEF = "invalid definition type for event type"
72_INVALID_EVENT_LEVEL_DEF = "invalid definition type for event level"
73_INVALID_EVENT_DESC_DEF = "invalid definition type for event desc"
74_INVALID_EVENT_TAG_DEF = "invalid definition type for event tag"
75_INVALID_EVENT_PRESERVE_DEF = "invalid definition type for event preserve"
76_INVALID_EVENT_PARAM_DEF = "invalid definition type for event param"
77_INVALID_PARAM_TYPE_DEF = "invalid definition type for param type"
78_INVALID_PARAM_ARRSIZE_DEF = "invalid definition type for param arrsize"
79_INVALID_PARAM_DESC_DEF = "invalid definition type for param desc"
80_WARNING_MAP = {
81    _EMPTY_YAML :
82        "The yaml file list is empty.",
83    _INVALID_YAML :
84        "Invalid yaml file, error message: <<%s>>.",
85    _DUPLICATE_DOMAIN :
86        "Domain <<%s>> is already defined in <<%s>>.",
87    _INVALID_DOMAIN_NUMBER :
88        "The domain definition is missing in the yaml file.",
89    _INVALID_DOMAIN_LENGTH :
90        "The length of the domain must be between [1, 16], "\
91        "but the actual length of the domain <<%s>> is <<%d>>.",
92    _INVALID_DOMAIN_CHAR :
93        "The character of the domain must be in [A-Z0-9_], "\
94        "but the domain <<%s>> actually has <<%c>>.",
95    _INVALID_DOMAIN_CHAR_HEAD :
96        "The header of the domain must be in [A-Z], "\
97        "but the actual header of the domain <<%s>> is <<%c>>.",
98    _INVALID_EVENT_NUMBER :
99        "The number of the events must be between [1, 4096], ."\
100        "but there are actually <<%d>> events.",
101    _INVALID_EVENT_LENGTH :
102        "The length of the event must be between [1, 32], "\
103        "but the actual length of the event <<%s>> is <<%d>>.",
104    _INVALID_EVENT_CHAR :
105        "The character of the event must be in [A-Z0-9_], "\
106        "but the event <<%s>> actually has <<%c>>.",
107    _INVALID_EVENT_CHAR_HEAD :
108        "The header of the event must be in [A-Z], "\
109        "but the actual header of the event <<%s>> is <<%c>>.",
110    _MISSING_EVENT_BASE :
111        "Event <<%s>> is missing __BASE definition.",
112    _MISSING_EVENT_TYPE :
113        "__BASE for event <<%s>> is missing type definition.",
114    _INVALID_EVENT_TYPE :
115        "The type of the event <<%s>> must be in "\
116        "[FAULT, STATISTIC, SECURITY, BEHAVIOR], "\
117        "but the actual event type is <<%s>>.",
118    _MISSING_EVENT_LEVEL :
119        "__BASE for event <<%s>> is missing level definition.",
120    _INVALID_EVENT_LEVEL :
121        "The level of the event <<%s>> must be in [CRITICAL, MINOR], "\
122        "but the actual event level is <<%s>>.",
123    _MISSING_EVENT_DESC :
124        "__BASE for event <<%s>> is missing desc definition.",
125    _INVALID_EVENT_DESC_LENGTH :
126        "The length of the event desc must be between [3, 128], "\
127        "but the actual length of the event <<%s>> desc <<%s>> is <<%d>>.",
128    _INVALID_EVENT_TAG_NUM :
129        "The number of the event tags must be between [0, 5], "\
130        "but actually the event <<%s>> tag <<%s>> has <<%d>> tags.",
131    _INVALID_EVENT_TAG_LEN :
132        "The length of the event tag must be between [1, 16], "\
133        "but the actual length of the event <<%s>> tag <<%s>> is <<%d>>.",
134    _INVALID_EVENT_TAG_CHAR :
135        "The character of the event tag must be in [A-Za-z0-9], "\
136        "but the event <<%s>> tag <<%s>> actually has <<%c>>.",
137    _DUPLICATE_EVENT_TAG :
138        "Event tag should not be duplicated, "\
139        "but tag <<%s>> for event <<%s>> has multiple identical.",
140    _INVALID_EVENT_BASE_KEY :
141        "Event <<%s>> __BASE key should be [type, level, tag, desc], "\
142        "but actually has an invalid key <<%s>>.",
143    _INVALID_EVENT_PARAM_NUM :
144        "The number of the event param must be between [0, 128], "\
145        "but actually the event <<%s>> has <<%d>> params.",
146    _INVALID_EVENT_PARAM_LEN :
147        "The length of the event param must be between [1, 32], "\
148        "but the actual length of the event <<%s>> param <<%s>> is <<%d>>.",
149    _INVALID_EVENT_PARAM_CHAR :
150        "The character of the event param must be in [A-Z0-9_], "\
151        "but the event <<%s>> param <<%s>> actually has <<%c>>.",
152    _INVALID_EVENT_PARAM_CHAR_HEAD:
153        "The header of the event param must be in [A-Z], "\
154        "but the actual header of the event <<%s>> param <<%s>> is <<%c>>.",
155    _MISSING_EVENT_PARAM_TYPE :
156        "Event <<%s>> param <<%s>> is missing type definition.",
157    _INVALID_EVENT_PARAM_TYPE :
158        "The type of the event <<%s>> param <<%s>> must be in "\
159        "[BOOL, INT8, UINT8, INT16, UINT16, INT32, UINT32, INT64, UINT64, "\
160        "FLOAT, DOUBLE, STRING], but the actual type is <<%s>>.",
161    _INVALID_EVENT_PARAM_ARRSIZE :
162        "The arrsize of the event param must be between [1, 100], "\
163        "but the actual arrsize of the event <<%s>> param <<%s>> is <<%d>>.",
164    _MISSING_EVENT_PARAM_DESC :
165        "Event <<%s>> param <<%s>> is missing desc definition.",
166    _INVALID_EVENT_PARAM_DESC_LEN :
167        "The length of the event param desc must be between [3, 128], "\
168        "but the actual length of the event <<%s>> param <<%s>> "\
169        "desc <<%s>> is <<%d>>.",
170    _INVALID_EVENT_PARAM_KEY :
171        "Event <<%s>> param <<%s>> key should be [type, arrsize, desc], "\
172        "but actually has an invalid key <<%s>>.",
173    _DEPRECATED_EVENT_NAME_PREFIX :
174        "Event <<%s>> should not start with domain <<%s>>.",
175    _DEPRECATED_PARAM_NAME_PREFIX :
176        "Event param <<%s>> should not start with event <<%s>>.",
177    _DEPRECATED_TAG_NAME :
178        "Event tag <<%s>> should not be same as %s <<%s>>.",
179    _DEPRECATED_EVENT_DESC_NAME :
180        "Event desc <<%s>> should not be same as event <<%s>> and "\
181        "should be more detailed.",
182    _DEPRECATED_PARAM_DESC_NAME :
183        "Event param desc <<%s>> should not be same as event <<%s>> "\
184        "param <<%s>> and should be more detailed.",
185    _INVALID_DOMAIN_DEF :
186        "The definition type of the domain must be string.",
187    _INVALID_EVENT_DEF :
188        "The definition type of the event <<%s>> must be dictionary.",
189    _INVALID_EVENT_BASE_DEF :
190        "The definition type of the event <<%s>> __BASE must be dictionary.",
191    _INVALID_EVENT_TYPE_DEF :
192        "The definition type of the event <<%s>> type must be string.",
193    _INVALID_EVENT_LEVEL_DEF :
194        "The definition type of the event <<%s>> level must be string.",
195    _INVALID_EVENT_DESC_DEF :
196        "The definition type of the event <<%s>> desc must be string.",
197    _INVALID_EVENT_TAG_DEF :
198        "The definition type of the event <<%s>> tag must be string.",
199    _INVALID_EVENT_PRESERVE_DEF :
200        "The definition type of the event <<%s>> preserve must be bool.",
201    _INVALID_EVENT_PARAM_DEF :
202        "The definition type of the event <<%s>> param <<%s>> "\
203        "must be dictionary.",
204    _INVALID_PARAM_TYPE_DEF :
205        "The definition type of the event <<%s>> param <<%s>> "\
206        "type must be string.",
207    _INVALID_PARAM_ARRSIZE_DEF :
208        "The definition type of the event <<%s>> param <<%s>> "\
209        "arrsize must be integer.",
210    _INVALID_PARAM_DESC_DEF :
211        "The definition type of the event <<%s>> param <<%s>> "\
212        "desc must be string.",
213    _DUPLICATE_KEY_DEF :
214        "Duplicate key <<%s>> exists%s.",
215}
216
217
218_domain_dict = {}
219_warning_dict = {}
220_warning_file_path = ""
221_yaml_file_path = ""
222_warning_file = None
223_hisysevent_parse_res = True
224_deprecated_dict = {}
225
226
227class _UniqueKeySafeLoader(yaml.SafeLoader):
228    def construct_mapping(self, node, deep=False):
229        mapping = []
230        for key_node, value_node in node.value:
231            key = self.construct_object(key_node, deep=deep)
232            if (key in mapping):
233                _build_warning_info(_DUPLICATE_KEY_DEF,
234                    (key, key_node.start_mark))
235                global _hisysevent_parse_res
236                _hisysevent_parse_res = False
237                continue
238            mapping.append(key)
239        return super().construct_mapping(node, deep)
240
241
242def _build_header(info_dict: dict):
243    table_header = "HiSysEvent yaml file: <<%s>>" % _yaml_file_path
244    info_dict[_yaml_file_path] = [table_header]
245    table_boundary = "-".rjust(100, '-')
246    info_dict[_yaml_file_path].append(table_boundary)
247    table_title = "Failed Item".ljust(50) + "|    " + "Failed Reason"
248    info_dict[_yaml_file_path].append(table_title)
249    info_dict[_yaml_file_path].append(table_boundary)
250
251
252def _build_warning_header():
253    global _warning_dict
254    _build_header(_warning_dict)
255
256
257def _build_deprecated_header():
258    global _deprecated_dict
259    _build_header(_deprecated_dict)
260
261
262def _build_warning_info(item, values):
263    detail = _WARNING_MAP[item] % values
264    content = item.ljust(50) + "|    " + detail
265    global _warning_dict
266    _warning_dict[_yaml_file_path].append(content)
267
268
269# Current set to warning, subsequent set to error.
270def _build_deprecated_info(item, values):
271    _build_deprecated_header()
272    detail = _WARNING_MAP[item] % values
273    content = item.ljust(50) + "|    " + detail
274    global _deprecated_dict
275    _deprecated_dict[_yaml_file_path].append(content)
276
277
278def _open_warning_file(output_path: str):
279    global _warning_file_path
280    _warning_file_path = os.path.join(output_path, 'hisysevent_warning.txt')
281    global _warning_file
282    _warning_file = open(_warning_file_path, 'w+')
283
284
285def _close_warning_file():
286    if not _warning_file:
287        _warning_file.close()
288
289
290def _output_warning():
291    for warning_list in _warning_dict.values():
292        if len(warning_list) > 4 or len(warning_list) == 1:
293            warning_list.append("")
294            for content in warning_list:
295                print(content)
296                print(content, file=_warning_file)
297
298
299def _output_deprecated(output_path: str):
300    deprecated_file = open(os.path.join(output_path, 'hisysevent_deprecated.txt'), 'w+')
301    for deprecated_list in _deprecated_dict.values():
302        deprecated_list.append("")
303        for content in deprecated_list:
304            print(content, file=deprecated_file)
305    if not deprecated_file:
306        deprecated_file.close()
307
308
309def _exit_sys():
310    print("Failed to parse the yaml file. For details about the error "\
311        "information, see file %s." % (_warning_file_path))
312    _output_warning()
313    _close_warning_file()
314    sys.exit(1)
315
316
317def _is_valid_length(content: str, len_min: int, len_max: int) -> bool:
318    return len(content) >= len_min and len(content) <= len_max
319
320
321def _is_valid_header(content: str) -> bool:
322    return len(content) == 0 or (content[0] >= 'A' and content[0] <= 'Z')
323
324
325def _is_invalid_char(ch) -> bool:
326    return (ch >= 'A' and ch <= 'Z') or (ch >= '0' and ch <= '9') or ch == '_'
327
328
329def _check_invalid_char(content: str):
330    for ch in iter(content):
331        if not _is_invalid_char(ch):
332            return ch
333    return None
334
335
336def _check_domain_duplicate(domain: str) -> bool:
337    if domain in _domain_dict:
338        _build_warning_info(_DUPLICATE_DOMAIN, (domain, _domain_dict[domain]))
339        return False
340    else:
341        _domain_dict[domain] = _yaml_file_path
342        return True
343
344
345def _check_event_domain(yaml_info: dict) -> bool:
346    if not "domain" in yaml_info:
347        _build_warning_info(_INVALID_DOMAIN_NUMBER, ())
348        return False
349    if not isinstance(yaml_info["domain"], str):
350        _build_warning_info(_INVALID_DOMAIN_DEF, ())
351        return False
352    domain = yaml_info["domain"]
353    check_res = True
354    if not _is_valid_length(domain, 1, 16):
355        _build_warning_info(_INVALID_DOMAIN_LENGTH, (domain, len(domain)))
356        check_res = False
357    if not _is_valid_header(domain):
358        _build_warning_info(_INVALID_DOMAIN_CHAR_HEAD, (domain, domain[0]))
359        check_res = False
360    invalid_ch = _check_invalid_char(domain)
361    if invalid_ch:
362        _build_warning_info(_INVALID_DOMAIN_CHAR, (domain, invalid_ch))
363        check_res = False
364    if not _check_domain_duplicate(domain):
365        check_res = False
366    return check_res
367
368
369def _check_yaml_format(yaml_info) -> bool:
370    if not yaml_info:
371        _build_warning_info(_INVALID_YAML, ("The yaml file is empty"))
372        return False
373    if not isinstance(yaml_info, dict):
374        _build_warning_info(_INVALID_YAML,
375            ("The content of yaml file is invalid"))
376        return False
377    return True
378
379
380def _check_event_name(domain: str, event_name: str) -> bool:
381    check_res = True
382    if not _is_valid_length(event_name, 1, 32):
383        _build_warning_info(_INVALID_EVENT_LENGTH,
384            (event_name, len(event_name)))
385        check_res = False
386    if len(domain) > 0 and event_name.startswith(domain):
387        _build_deprecated_info(_DEPRECATED_EVENT_NAME_PREFIX,
388            (event_name, domain))
389    if not _is_valid_header(event_name):
390        _build_warning_info(_INVALID_EVENT_CHAR_HEAD,
391            (event_name, event_name[0]))
392        check_res = False
393    invalid_ch = _check_invalid_char(event_name)
394    if invalid_ch:
395        _build_warning_info(_INVALID_DOMAIN_CHAR, (event_name, invalid_ch))
396        check_res = False
397    return check_res
398
399
400def _check_event_type(event_name: str, event_base: dict) -> bool:
401    if not "type" in event_base:
402        _build_warning_info(_MISSING_EVENT_TYPE, (event_name))
403        return False
404    else:
405        if not isinstance(event_base["type"], str):
406            _build_warning_info(_INVALID_EVENT_TYPE_DEF, event_name)
407            return False
408        type_list = ["FAULT", "STATISTIC", "SECURITY", "BEHAVIOR"]
409        if not event_base["type"] in type_list:
410            _build_warning_info(_INVALID_EVENT_TYPE,
411                (event_name, event_base["type"]))
412            return False
413    return True
414
415
416def _check_event_level(event_name: str, event_base: dict) -> bool:
417    if not "level" in event_base:
418        _build_warning_info(_MISSING_EVENT_LEVEL, (event_name))
419        return False
420    else:
421        if not isinstance(event_base["level"], str):
422            _build_warning_info(_INVALID_EVENT_LEVEL_DEF, event_name)
423            return False
424        level_list = ["CRITICAL", "MINOR"]
425        if not event_base["level"] in level_list:
426            _build_warning_info(_INVALID_EVENT_LEVEL,
427                (event_name, event_base["level"]))
428            return False
429    return True
430
431
432def _check_event_desc(event_name: str, event_base: dict) -> bool:
433    if not "desc" in event_base:
434        _build_warning_info(_MISSING_EVENT_DESC, (event_name))
435        return False
436    else:
437        event_desc = event_base["desc"]
438        if not isinstance(event_desc, str):
439            _build_warning_info(_INVALID_EVENT_DESC_DEF, event_name)
440            return False
441        check_res = True
442        if event_desc.lower() == event_name.lower():
443            _build_deprecated_info(_DEPRECATED_EVENT_DESC_NAME,
444                (event_desc, event_name))
445        if not _is_valid_length(event_desc, 3, 128):
446            _build_warning_info(_INVALID_EVENT_DESC_LENGTH,
447                (event_name, event_desc, len(event_desc)))
448            check_res = False
449        return check_res
450
451
452def _check_tag_char(event_tag: list):
453    for ch in iter(event_tag):
454        if not ch.isalnum():
455            return ch
456    return None
457
458
459def _check_tag_name(event_name: str, event_base: dict, tag_name: str) -> bool:
460    check_res = True
461    if tag_name.lower() == event_name.lower():
462        _build_deprecated_info(_DEPRECATED_TAG_NAME,
463            (tag_name, "event", event_name))
464    if "type" in event_base and tag_name.lower() == event_base["type"].lower():
465        _build_deprecated_info(_DEPRECATED_TAG_NAME,
466            (tag_name, "event type", event_base["type"]))
467    if not _is_valid_length(tag_name, 1, 16):
468        _build_warning_info(_INVALID_EVENT_TAG_LEN,
469            (event_name, tag_name, len(tag_name)))
470        check_res = False
471    invalid_ch = _check_tag_char(tag_name)
472    if invalid_ch:
473        _build_warning_info(_INVALID_EVENT_TAG_CHAR,
474            (event_name, tag_name, invalid_ch))
475        check_res = False
476    return check_res
477
478
479def _get_duplicate_tag(tag_list: list):
480    tag_dict = dict(Counter(tag_list))
481    for key, value in tag_dict.items():
482        if value > 1:
483            return key
484    return None
485
486
487def _check_event_tag(event_name: str, event_base: dict) -> bool:
488    if not "tag" in event_base:
489        return True
490    event_tag = event_base["tag"]
491    if not isinstance(event_tag, str):
492        _build_warning_info(_INVALID_EVENT_TAG_DEF, event_name)
493        return False
494    tag_list = event_tag.split()
495    if not _is_valid_length(tag_list, 1, 5):
496        _build_warning_info(_INVALID_EVENT_TAG_NUM,
497            (event_name, event_tag, len(tag_list)))
498        return False
499    check_res = True
500    for each_tag in tag_list:
501        if not _check_tag_name(event_name, event_base, each_tag):
502            check_res = False
503    dup_tag = _get_duplicate_tag(tag_list)
504    if dup_tag:
505        _build_warning_info(_DUPLICATE_EVENT_TAG, (dup_tag, event_name))
506        check_res = False
507    return check_res
508
509
510def _check_event_preserve(event_name: str, event_base: dict) -> bool:
511    if not "preserve" in event_base:
512        return True
513    event_preserve = event_base["preserve"]
514    if not isinstance(event_preserve, bool):
515        _build_warning_info(_INVALID_EVENT_PRESERVE_DEF, event_name)
516        return False
517    return True
518
519
520def _check_base_key(event_name: str, event_base: dict) -> bool:
521    key_list = ["type", "level", "tag", "desc", "preserve"]
522    for base_key in event_base.keys():
523        if not base_key in key_list:
524            _build_warning_info(_INVALID_EVENT_BASE_KEY,
525                (event_name, base_key))
526            return False
527    return True
528
529
530def _check_event_base(event_name: str, event_def: str) -> bool:
531    if not "__BASE" in event_def:
532        _build_warning_info(_MISSING_EVENT_BASE, (event_name))
533        return False
534    event_base = event_def["__BASE"]
535    if not isinstance(event_base, dict):
536        _build_warning_info(_INVALID_EVENT_BASE_DEF, (event_name))
537        return False
538    check_res = True
539    if not _check_event_type(event_name, event_base):
540        check_res = False
541    if not _check_event_level(event_name, event_base):
542        check_res = False
543    if not _check_event_desc(event_name, event_base):
544        check_res = False
545    if not _check_event_tag(event_name, event_base):
546        check_res = False
547    if not _check_event_preserve(event_name, event_base):
548        check_res = False
549    if not _check_base_key(event_name, event_base):
550        check_res = False
551    return check_res
552
553
554def _check_param_name(event_name: str, name: str) -> bool:
555    check_res = True
556    if not _is_valid_length(name, 1, 32):
557        _build_warning_info(_INVALID_EVENT_PARAM_LEN,
558            (event_name, name, len(name)))
559        check_res = False
560    if len(event_name) > 0 and name.startswith(event_name):
561        _build_deprecated_info(_DEPRECATED_PARAM_NAME_PREFIX, (name, event_name))
562    if not _is_valid_header(name):
563        _build_warning_info(_INVALID_EVENT_PARAM_CHAR_HEAD,
564            (event_name, name, name[0]))
565        check_res = False
566    invalid_ch = _check_invalid_char(name)
567    if invalid_ch:
568        _build_warning_info(_INVALID_EVENT_PARAM_CHAR,
569            (event_name, name, invalid_ch))
570        check_res = False
571    return check_res
572
573
574def _check_param_type(event_name: str, param_name: str, param_info: dict) -> bool:
575    if not "type" in param_info:
576        _build_warning_info(_MISSING_EVENT_PARAM_TYPE,
577            (event_name, param_name))
578        return False
579    else:
580        if not isinstance(param_info["type"], str):
581            _build_warning_info(_INVALID_PARAM_TYPE_DEF,
582                (event_name, param_name))
583            return False
584        type_list = ["BOOL", "INT8", "UINT8", "INT16", "UINT16", "INT32",
585            "UINT32", "INT64", "UINT64", "FLOAT", "DOUBLE", "STRING"]
586        if not param_info["type"] in type_list:
587            _build_warning_info(_INVALID_EVENT_PARAM_TYPE,
588                (event_name, param_name, param_info["type"]))
589            return False
590    return True
591
592
593def _check_param_arrsize(event_name: str, param_name: str, param_info: dict) -> bool:
594    if not "arrsize" in param_info:
595        return True
596    arrsize = param_info["arrsize"]
597    if not isinstance(arrsize, int):
598        _build_warning_info(_INVALID_PARAM_ARRSIZE_DEF,
599            (event_name, param_name))
600        return False
601    if not (arrsize >= 1 and arrsize <= 100):
602        _build_warning_info(_INVALID_EVENT_PARAM_ARRSIZE,
603            (event_name, param_name, arrsize))
604        return False
605    return True
606
607
608def _check_param_desc(event_name: str, param_name: str, param_info: dict) -> bool:
609    if not "desc" in param_info:
610        _build_warning_info(_MISSING_EVENT_PARAM_DESC,
611            (event_name, param_name))
612        return False
613    else:
614        param_desc = param_info["desc"]
615        if not isinstance(param_desc, str):
616            _build_warning_info(_INVALID_PARAM_DESC_DEF,
617                (event_name, param_name))
618            return False
619        check_res = True
620        if param_desc.lower() == param_name.lower():
621            _build_deprecated_info(_DEPRECATED_PARAM_DESC_NAME,
622                (param_desc, event_name, param_name))
623        if not _is_valid_length(param_desc, 3, 128):
624            _build_warning_info(_INVALID_EVENT_PARAM_DESC_LEN,
625                (event_name, param_name, param_desc, len(param_desc)))
626            check_res = False
627        return check_res
628
629
630def _check_param_key(event_name: str, param_name: str, param_info: dict) -> bool:
631    key_list = ["type", "arrsize", "desc"]
632    for key in param_info.keys():
633        if not key in key_list:
634            _build_warning_info(_INVALID_EVENT_PARAM_KEY,
635                (event_name, param_name, key))
636            return False
637    return True
638
639
640def _check_param_info(event_name: str, param_name: str, param_info: dict) -> bool:
641    check_res = True
642    if not _check_param_type(event_name, param_name, param_info):
643        check_res = False
644    if not _check_param_arrsize(event_name, param_name, param_info):
645        check_res = False
646    if not _check_param_desc(event_name, param_name, param_info):
647        check_res = False
648    if not _check_param_key(event_name, param_name, param_info):
649        check_res = False
650    return check_res
651
652
653def _check_event_param(event_name: str, event_def: str) -> bool:
654    sub_num = (0, 1)["__BASE" in event_def]
655    check_res = True
656    if not _is_valid_length(event_def, 0 + sub_num, 128 + sub_num):
657        _build_warning_info(_INVALID_EVENT_PARAM_NUM,
658            (event_name, (len(event_def) - sub_num)))
659        check_res = False
660    for param_name in event_def.keys():
661        if param_name == "__BASE":
662            continue
663        if not _check_param_name(event_name, param_name):
664            check_res = False
665        param_info = event_def[param_name]
666        if not isinstance(param_info, dict):
667            _build_warning_info(_INVALID_EVENT_PARAM_DEF,
668                (event_name, param_name))
669            check_res = False
670            continue
671        if not _check_param_info(event_name, param_name, param_info):
672            check_res = False
673    return check_res
674
675
676def _check_event_def(event_name: str, event_def: str) -> bool:
677    check_res = True
678    if not _check_event_base(event_name, event_def):
679        check_res = False
680    if not _check_event_param(event_name, event_def):
681        check_res = False
682    return check_res
683
684
685def _check_event_info(domain: str, event_info: list) -> bool:
686    event_name = event_info[0]
687    event_def = event_info[1]
688    check_res = True
689    if not isinstance(event_def, dict):
690        _build_warning_info(_INVALID_EVENT_DEF, (event_name))
691        return False
692    if not _check_event_name(domain, event_name):
693        check_res = False
694    if not _check_event_def(event_name, event_def):
695        check_res = False
696    return check_res
697
698
699def _check_events_info(domain: str, yaml_info: str) -> bool:
700    event_num = len(yaml_info)
701    if not (event_num >= 1 and event_num <= 4096):
702        _build_warning_info(_INVALID_EVENT_NUMBER, (event_num))
703        return False
704    check_res = True
705    for event_info in yaml_info.items():
706        if not _check_event_info(domain, event_info):
707            check_res = False
708    return check_res
709
710
711def merge_hisysevent_config(yaml_list: str, output_path: str) -> str:
712    if (len(output_path) == 0):
713        present_path = os.path.dirname(os.path.abspath(__file__))
714        output_path = present_path
715    if (len(yaml_list) == 0):
716        _build_warning_info(_EMPTY_YAML, ())
717        _exit_sys()
718    if not os.path.exists(output_path):
719        os.makedirs(output_path, exist_ok=True)
720    _open_warning_file(output_path)
721
722    yaml_info_dict = {}
723    global _hisysevent_parse_res
724    for yaml_path in yaml_list:
725        global _yaml_file_path
726        _yaml_file_path = yaml_path.replace("../", "")
727        _build_warning_header()
728        yaml_file = open(yaml_path, 'r')
729        yaml_info = yaml.load(yaml_file, Loader=_UniqueKeySafeLoader)
730        if not _check_yaml_format(yaml_info):
731            _hisysevent_parse_res = False
732            continue
733        if not _check_event_domain(yaml_info):
734            _hisysevent_parse_res = False
735            continue
736        domain = yaml_info["domain"]
737        del yaml_info["domain"]
738        if not _check_events_info(domain, yaml_info):
739            _hisysevent_parse_res = False
740            continue
741        yaml_info_dict[domain] = yaml_info
742    _output_deprecated(output_path)
743    if not _hisysevent_parse_res:
744        _exit_sys()
745
746    hisysevent_def_file = os.path.join(output_path, 'hisysevent.def')
747    with open(hisysevent_def_file, 'w') as j:
748        json.dump(yaml_info_dict, j, indent=4)
749    print("The hisysevent.def {} is generated successfully."
750        .format(hisysevent_def_file))
751    _close_warning_file()
752    return hisysevent_def_file
753
754
755def main(argv) -> int:
756    parser = argparse.ArgumentParser(description='yaml list')
757    parser.add_argument("--yaml-list", nargs='+', required=True)
758    parser.add_argument("--def-path", required=True)
759    args = parser.parse_args(argv)
760    hisysevent_def_file = merge_hisysevent_config(args.yaml_list,
761        args.def_path)
762    print(hisysevent_def_file)
763    return 0
764
765
766if __name__ == '__main__':
767    sys.exit(main(sys.argv[1:]))
768