1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #import "header_generator.h"
6 
7 using std::map;
8 using std::string;
9 using std::vector;
10 
add_attribute(map<string,string> attributes,const string & attribute)11 static const string add_attribute(map<string, string> attributes,
12                                   const string& attribute) {
13     auto ft = attributes.find(attribute);
14     return (ft == attributes.end()) ? string() : ft->second;
15 }
16 
collect_nonnull(const Syscall & sc)17 static vector<int> collect_nonnull(const Syscall& sc) {
18     vector<int> nonnull;
19     int out_idx = static_cast<int>(sc.arg_spec.size());
20     sc.for_each_return([&](const TypeSpec& type) {
21         ++out_idx;
22         if (!has_attribute("optional", type.attributes))
23             nonnull.push_back(out_idx);
24     });
25     return nonnull;
26 }
27 
syscall(std::ofstream & os,const Syscall & sc)28 bool HeaderGenerator::syscall(std::ofstream& os, const Syscall& sc) {
29     constexpr uint32_t indent_spaces = 4u;
30 
31     for (const auto& name_prefix : name_prefixes_) {
32         if (name_prefix.second(sc))
33             continue;
34 
35         auto syscall_name = name_prefix.first + sc.name;
36 
37         os << function_prefix_;
38 
39         write_syscall_signature_line(
40             os, sc, name_prefix.first,
41             "\n" + string(indent_spaces, ' '),
42             "\n" + string(indent_spaces, ' '),
43             allow_pointer_wrapping_ && !sc.is_vdso(),
44             no_args_type_);
45 
46         if (!allow_pointer_wrapping_) {
47             const vector<int> nonnull = collect_nonnull(sc);
48             if (!nonnull.empty()) {
49                 os << " __NONNULL((";
50                 for (int idx : nonnull) {
51                     os << idx << ", ";
52                 }
53                 os.seekp(-2, std::ios_base::end);
54                 os << "))";
55             }
56         }
57 
58         os << " ";
59 
60         // Writes attributes after arguments.
61         for (const auto& attr : sc.attributes) {
62             auto a = add_attribute(attributes_, attr);
63             if (!a.empty())
64                 os << a << " ";
65         }
66 
67         if (sc.ret_spec.size() > 0)
68             write_argument_annotation(os, sc.ret_spec[0]);
69 
70         os.seekp(-1, std::ios_base::end);
71 
72         os << ";\n\n";
73     }
74 
75     return os.good();
76 }
77