1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "codegen/code_generator.h"
17#include "parser/parser.h"
18#include "preprocessor/preprocessor.h"
19#include "util/file.h"
20#include "util/logger.h"
21#include "util/options.h"
22#include "hash/hash.h"
23#include "metadata/metadata_builder.h"
24#include "metadata/metadata_dumper.h"
25#include "metadata/metadata_reader.h"
26#include "metadata/metadata_serializer.h"
27
28using namespace OHOS::Idl;
29
30static int FileParse(Parser &parser)
31{
32    std::vector<FileDetail> fileDetails;
33    if (!Preprocessor::Preprocess(fileDetails)) {
34        Logger::E(TAG, "failed to preprocess");
35        return -1;
36    }
37
38    if (!parser.Parse(fileDetails)) {
39        Logger::E(TAG, "failed to parse file");
40        return -1;
41    }
42
43    return 0;
44}
45
46static void DumpAst(const StrAstMap &allAst)
47{
48    const Options &options = Options::GetInstance();
49    if (!options.DoDumpAST()) {
50        return;
51    }
52    for (const auto &astPair : allAst) {
53        AutoPtr<AST> ast = astPair.second;
54        if ((options.GetInterfaceType() == InterfaceType::SA) &&
55            (ast->GetASTFileType() != ASTFileType::AST_IFACE)) {
56            continue;
57        }
58        if (astPair.second != nullptr) {
59            printf("%s\n", astPair.second->Dump("").c_str());
60        }
61    }
62}
63
64static int DumpMetaData(const StrAstMap &allAst)
65{
66    Options &options = Options::GetInstance();
67    if ((options.GetInterfaceType() != InterfaceType::SA)) {
68        return 0;
69    }
70
71    AutoPtr<AST> ast;
72    for (const auto &astPair : allAst) {
73        ast = astPair.second;
74        if (ast->GetASTFileType() == ASTFileType::AST_IFACE) {
75            break;
76        }
77    }
78    MetadataBuilder builder(ast);
79    std::shared_ptr<MetaComponent> metadata = builder.Build();
80    if (metadata == nullptr) {
81        Logger::E(TAG, "Generate metadata failed.");
82        return -1;
83    }
84
85    if (options.DoDumpMetadata()) {
86        MetadataDumper dumper(metadata.get());
87        printf("%s", dumper.Dump("").c_str());
88    }
89
90    if (options.DoSaveMetadata()) {
91        File metadataFile(options.GetMetadataFile(), File::WRITE);
92        if (!metadataFile.IsValid()) {
93            Logger::E(TAG, "Create metadata file failed.");
94            return -1;
95        }
96
97        MetadataSerializer serializer(metadata.get());
98        serializer.Serialize();
99        uintptr_t data = serializer.GetData();
100        int size = serializer.GetDataSize();
101
102        metadataFile.WriteData(reinterpret_cast<void*>(data), size);
103        metadataFile.Flush();
104        metadataFile.Close();
105    }
106    return 0;
107}
108
109static int ReadMetaData(StrAstMap &astList)
110{
111    const Options &options = Options::GetInstance();
112    if ((options.GetInterfaceType() != InterfaceType::SA) || options.DoCompile()) {
113        return 0;
114    }
115    std::string metadataFile = options.GetMetadataFile();
116    std::shared_ptr<MetaComponent> metadata = MetadataReader::ReadMetadataFromFile(metadataFile);
117    if (metadata == nullptr) {
118        Logger::E(TAG, "Get metadata from \"%s\" failed.", metadataFile.c_str());
119        return -1;
120    }
121
122    MetadataReader reader(metadata.get());
123    astList = reader.ReadMetadataToAst();
124    return 0;
125}
126
127int main(int argc, char **argv)
128{
129    Options &options = Options::GetInstance();
130    if (!options.Parse(argc, argv)) {
131        return -1;
132    }
133
134    if (options.DoShowUsage()) {
135        options.ShowUsage();
136        return 0;
137    }
138    if (options.DoShowVersion()) {
139        options.ShowVersion();
140        return 0;
141    }
142    if (options.HasWarning()) {
143        options.ShowWarning();
144    }
145
146    if (options.DoGetHashKey()) {
147        return Hash::GenHashKey() ? 0 : -1;
148    }
149
150    StrAstMap astList;
151    Parser parser;
152    if (options.DoCompile()) {
153        if (FileParse(parser) != 0) {
154            return -1;
155        }
156
157        astList = parser.GetAllAst();
158        DumpAst(astList);
159
160        if (DumpMetaData(astList) != 0) {
161            return -1;
162        }
163    }
164
165    if (!options.DoGenerateCode()) {
166        return 0;
167    }
168
169    if (ReadMetaData(astList) != 0) {
170        return -1;
171    }
172
173    if (!CodegenBuilder::GetInstance().Generate(astList)) {
174        Logger::E(TAG, "failed to generate code");
175        return -1;
176    }
177    return 0;
178}