1 /*
2 * Copyright (c) 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 "codegen/c_code_emitter.h"
10 #include "util/options.h"
11
12 namespace OHOS {
13 namespace HDI {
GetImportInclusions(HeaderFile::HeaderFileSet & headerFiles)14 void CCodeEmitter::GetImportInclusions(HeaderFile::HeaderFileSet &headerFiles)
15 {
16 for (const auto &importPair : ast_->GetImports()) {
17 AutoPtr<AST> importAst = importPair.second;
18 std::string fileName = PackageToFilePath(importAst->GetFullName());
19 headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, fileName);
20 }
21 }
22
EmitInterfaceMethodParameter(const AutoPtr<ASTParameter> & parameter,StringBuilder & sb,const std::string & prefix)23 void CCodeEmitter::EmitInterfaceMethodParameter(
24 const AutoPtr<ASTParameter> ¶meter, StringBuilder &sb, const std::string &prefix)
25 {
26 sb.Append(prefix).Append(parameter->EmitCParameter());
27 }
28
EmitMethodNeedLoopVar(const AutoPtr<ASTMethod> & method,bool needRW,bool needFree,StringBuilder & sb,const std::string & prefix)29 void CCodeEmitter::EmitMethodNeedLoopVar(
30 const AutoPtr<ASTMethod> &method, bool needRW, bool needFree, StringBuilder &sb, const std::string &prefix)
31 {
32 if (!isKernelCode_) {
33 return;
34 }
35
36 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
37 AutoPtr<ASTParameter> param = method->GetParameter(i);
38 if (EmitNeedLoopVar(param->GetType(), needRW, needFree)) {
39 sb.Append(prefix).Append("uint32_t i = 0;\n");
40 break;
41 }
42 }
43 }
44
EmitNeedLoopVar(const AutoPtr<ASTType> & type,bool needRW,bool needFree)45 bool CCodeEmitter::EmitNeedLoopVar(const AutoPtr<ASTType> &type, bool needRW, bool needFree)
46 {
47 if (type == nullptr) {
48 return false;
49 }
50
51 auto rwNeedLoopVar = [needRW](const AutoPtr<ASTType> &elementType) -> bool {
52 if (!needRW) {
53 return false;
54 }
55
56 if (elementType->IsPod()) {
57 return elementType->IsBooleanType() ? true : false;
58 }
59
60 return elementType->IsStringType() ? false : true;
61 };
62
63 auto freeNeedLoopVar = [needFree](const AutoPtr<ASTType> &elementType) -> bool {
64 if (!needFree) {
65 return false;
66 }
67 return elementType->IsPod() ? false : true;
68 };
69
70 if (type->IsArrayType()) {
71 AutoPtr<ASTArrayType> ArrType = dynamic_cast<ASTArrayType *>(type.Get());
72 if (rwNeedLoopVar(ArrType->GetElementType()) || freeNeedLoopVar(ArrType->GetElementType())) {
73 return true;
74 }
75 } else if (type->IsListType()) {
76 AutoPtr<ASTListType> ListType = dynamic_cast<ASTListType *>(type.Get());
77 if (rwNeedLoopVar(ListType->GetElementType()) || freeNeedLoopVar(ListType->GetElementType())) {
78 return true;
79 }
80 }
81
82 return false;
83 }
84
EmitErrorHandle(const AutoPtr<ASTMethod> & method,const std::string & gotoLabel,bool isClient,StringBuilder & sb,const std::string & prefix)85 void CCodeEmitter::EmitErrorHandle(const AutoPtr<ASTMethod> &method, const std::string &gotoLabel, bool isClient,
86 StringBuilder &sb, const std::string &prefix)
87 {
88 if (!isClient) {
89 sb.Append(prefix).AppendFormat("%s:\n", gotoLabel.c_str());
90 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
91 AutoPtr<ASTParameter> param = method->GetParameter(i);
92 AutoPtr<ASTType> paramType = param->GetType();
93 paramType->EmitMemoryRecycle(param->GetName(), isClient, true, sb, prefix + TAB);
94 }
95 return;
96 }
97 }
98
EmitLicense(StringBuilder & sb)99 void CCodeEmitter::EmitLicense(StringBuilder &sb)
100 {
101 if (ast_->GetLicense().empty()) {
102 return;
103 }
104 sb.Append(ast_->GetLicense()).Append("\n\n");
105 }
106
EmitHeadMacro(StringBuilder & sb,const std::string & fullName)107 void CCodeEmitter::EmitHeadMacro(StringBuilder &sb, const std::string &fullName)
108 {
109 std::string macroName = MacroName(fullName);
110 sb.Append("#ifndef ").Append(macroName).Append("\n");
111 sb.Append("#define ").Append(macroName).Append("\n");
112 }
113
EmitTailMacro(StringBuilder & sb,const std::string & fullName)114 void CCodeEmitter::EmitTailMacro(StringBuilder &sb, const std::string &fullName)
115 {
116 std::string macroName = MacroName(fullName);
117 sb.Append("#endif // ").Append(macroName);
118 }
119
EmitHeadExternC(StringBuilder & sb)120 void CCodeEmitter::EmitHeadExternC(StringBuilder &sb)
121 {
122 sb.Append("#ifdef __cplusplus\n");
123 sb.Append("extern \"C\" {\n");
124 sb.Append("#endif /* __cplusplus */\n");
125 }
126
EmitTailExternC(StringBuilder & sb)127 void CCodeEmitter::EmitTailExternC(StringBuilder &sb)
128 {
129 sb.Append("#ifdef __cplusplus\n");
130 sb.Append("}\n");
131 sb.Append("#endif /* __cplusplus */\n");
132 }
133
MacroName(const std::string & name)134 std::string CCodeEmitter::MacroName(const std::string &name)
135 {
136 if (name.empty()) {
137 return name;
138 }
139
140 std::string macro = StringHelper::StrToUpper(StringHelper::Replace(name, '.', '_')) + "_H";
141 return macro;
142 }
143
SpecificationParam(StringBuilder & paramSb,const std::string & prefix)144 std::string CCodeEmitter::SpecificationParam(StringBuilder ¶mSb, const std::string &prefix)
145 {
146 size_t maxLineLen = 120;
147 size_t replaceLen = 2;
148 std::string paramStr = paramSb.ToString();
149 size_t preIndex = 0;
150 size_t curIndex = 0;
151
152 std::string insertStr = StringHelper::Format("\n%s", prefix.c_str());
153 for (; curIndex < paramStr.size(); curIndex++) {
154 if (curIndex == maxLineLen && preIndex > 0) {
155 StringHelper::Replace(paramStr, preIndex, replaceLen, ",");
156 paramStr.insert(preIndex + 1, insertStr);
157 } else {
158 if (paramStr[curIndex] == ',') {
159 preIndex = curIndex;
160 }
161 }
162 }
163 return paramStr;
164 }
165 } // namespace HDI
166 } // namespace OHOS