Line data Source code
1 : /* 2 : * Licensed to the Apache Software Foundation (ASF) under one 3 : * or more contributor license agreements. See the NOTICE file 4 : * distributed with this work for additional information 5 : * regarding copyright ownership. The ASF licenses this file 6 : * to you under the Apache License, Version 2.0 (the 7 : * "License"); you may not use this file except in compliance 8 : * with the License. You may obtain a copy of the License at 9 : * 10 : * http://www.apache.org/licenses/LICENSE-2.0 11 : * 12 : * Unless required by applicable law or agreed to in writing, 13 : * software distributed under the License is distributed on an 14 : * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 : * KIND, either express or implied. See the License for the 16 : * specific language governing permissions and limitations 17 : * under the License. 18 : */ 19 : 20 : #ifndef T_PROGRAM_H 21 : #define T_PROGRAM_H 22 : 23 : #include <map> 24 : #include <string> 25 : #include <vector> 26 : 27 : // For program_name() 28 : #include "main.h" 29 : 30 : #include "t_doc.h" 31 : #include "t_scope.h" 32 : #include "t_base_type.h" 33 : #include "t_typedef.h" 34 : #include "t_enum.h" 35 : #include "t_const.h" 36 : #include "t_struct.h" 37 : #include "t_service.h" 38 : #include "t_list.h" 39 : #include "t_map.h" 40 : #include "t_set.h" 41 : #ifdef SANDESH 42 : #include "t_sandesh.h" 43 : #endif 44 : #include "generate/t_generator_registry.h" 45 : //#include "t_doc.h" 46 : 47 : /** 48 : * Top level class representing an entire thrift program. A program consists 49 : * fundamentally of the following: 50 : * 51 : * Typedefs 52 : * Enumerations 53 : * Constants 54 : * Structs 55 : * Exceptions 56 : * Services 57 : #ifdef SANDESH 58 : * Sandeshs 59 : #endif 60 : * 61 : * The program module also contains the definitions of the base types. 62 : * 63 : */ 64 : class t_program : public t_doc { 65 : public: 66 : t_program(std::string path, std::string name) : 67 : path_(path), 68 : name_(name), 69 : out_path_("./"), 70 : out_path_is_absolute_(false) { 71 : scope_ = new t_scope(); 72 : } 73 : 74 776 : t_program(std::string path) : 75 776 : path_(path), 76 776 : out_path_("./"), 77 2328 : out_path_is_absolute_(false) { 78 776 : name_ = program_name(path); 79 776 : scope_ = new t_scope(); 80 776 : } 81 : 82 : // Path accessor 83 1338 : const std::string& get_path() const { return path_; } 84 : 85 : // Output path accessor 86 2506 : const std::string& get_out_path() const { return out_path_; } 87 : 88 : // Create gen-* dir accessor 89 2506 : bool is_out_path_absolute() { return out_path_is_absolute_; } 90 : 91 : // Name accessor 92 3503 : const std::string& get_name() const { return name_; } 93 : 94 : // Namespace 95 : const std::string& get_namespace() const { return namespace_; } 96 : 97 : // Include prefix accessor 98 1350 : const std::string& get_include_prefix() const { return include_prefix_; } 99 : 100 : // Accessors for program elements 101 398 : const std::vector<t_typedef*>& get_typedefs() const { return typedefs_; } 102 960 : const std::vector<t_enum*>& get_enums() const { return enums_; } 103 398 : const std::vector<t_const*>& get_consts() const { return consts_; } 104 562 : const std::vector<t_struct*>& get_structs() const { return structs_; } 105 562 : const std::vector<t_struct*>& get_xceptions() const { return xceptions_; } 106 936 : const std::vector<t_struct*>& get_objects() const { return objects_; } 107 563 : const std::vector<t_service*>& get_services() const { return services_; } 108 : #ifdef SANDESH 109 1630 : const std::vector<t_sandesh*>& get_sandeshs() const { return sandeshs_; } 110 : #endif 111 : 112 : // Program elements 113 4 : void add_typedef (t_typedef* td) { typedefs_.push_back(td); } 114 505 : void add_enum (t_enum* te) { enums_.push_back(te); } 115 3481 : void add_const (t_const* tc) { consts_.push_back(tc); } 116 4524 : void add_struct (t_struct* ts) { objects_.push_back(ts); 117 4524 : structs_.push_back(ts); } 118 0 : void add_xception (t_struct* tx) { objects_.push_back(tx); 119 0 : xceptions_.push_back(tx); } 120 0 : void add_service (t_service* ts) { services_.push_back(ts); } 121 : #ifdef SANDESH 122 5804 : void add_sandesh (t_sandesh* ts) { sandeshs_.push_back(ts); } 123 : #endif 124 : 125 : // Programs to include 126 35 : const std::vector<t_program*>& get_includes() const { return includes_; } 127 : 128 562 : void set_out_path(std::string out_path, bool out_path_is_absolute) { 129 562 : out_path_ = out_path; 130 562 : out_path_is_absolute_ = out_path_is_absolute; 131 : // Ensure that it ends with a trailing '/') 132 562 : char c = out_path_.at(out_path_.size() - 1); 133 562 : if (!(c == '/')) { 134 561 : out_path_.push_back('/'); 135 : } 136 562 : } 137 : 138 : // Scoping and namespacing 139 : void set_namespace(std::string name) { 140 : namespace_ = name; 141 : } 142 : 143 : // Scope accessor 144 1766 : t_scope* scope() { 145 1766 : return scope_; 146 : } 147 : 148 : // Includes 149 : 150 214 : void add_include(std::string path, std::string include_site) { 151 214 : t_program* program = new t_program(path); 152 : 153 : // include prefix for this program is the site at which it was included 154 : // (minus the filename) 155 214 : std::string include_prefix; 156 214 : std::string::size_type last_slash = std::string::npos; 157 214 : if ((last_slash = include_site.rfind("/")) != std::string::npos) { 158 214 : include_prefix = include_site.substr(0, last_slash); 159 : } 160 : 161 214 : program->set_include_prefix(include_prefix); 162 214 : includes_.push_back(program); 163 214 : } 164 : 165 1174 : std::vector<t_program*>& get_includes() { 166 1174 : return includes_; 167 : } 168 : 169 776 : void set_include_prefix(std::string include_prefix) { 170 776 : include_prefix_ = include_prefix; 171 : 172 : // this is intended to be a directory; add a trailing slash if necessary 173 776 : int len = include_prefix_.size(); 174 776 : if (len > 0 && include_prefix_[len - 1] != '/') { 175 776 : include_prefix_ += '/'; 176 : } 177 776 : } 178 : 179 : // Language neutral namespace / packaging 180 94 : void set_namespace(std::string language, std::string name_space) { 181 : #if 0 182 : if (language != "*") { 183 : size_t sub_index = language.find('.'); 184 : std::string base_language = language.substr(0, sub_index); 185 : std::string sub_namespace; 186 : 187 : if(base_language == "smalltalk") { 188 : pwarning(1, "Namespace 'smalltalk' is deprecated. Use 'st' instead"); 189 : base_language = "st"; 190 : } 191 : 192 : t_generator_registry::gen_map_t my_copy = t_generator_registry::get_generator_map(); 193 : 194 : t_generator_registry::gen_map_t::iterator it; 195 : it=my_copy.find(base_language); 196 : 197 : if (it == my_copy.end()) { 198 : throw "No generator named '" + base_language + "' could be found!"; 199 : } 200 : 201 : if (sub_index != std::string::npos) { 202 : std::string sub_namespace = language.substr(sub_index+1); 203 : if(! it->second->is_valid_namespace(sub_namespace)) { 204 : throw base_language +" generator does not accept '" + sub_namespace + "' as sub-namespace!"; 205 : } 206 : } 207 : } 208 : #endif 209 : 210 94 : namespaces_[language] = name_space; 211 94 : } 212 : 213 2488 : std::string get_namespace(std::string language) const { 214 2488 : std::map<std::string, std::string>::const_iterator iter; 215 4257 : if ((iter = namespaces_.find(language)) != namespaces_.end() || 216 4257 : (iter = namespaces_.find("*" )) != namespaces_.end()) { 217 719 : return iter->second; 218 : } 219 1769 : return std::string(); 220 : } 221 : 222 : // Language specific namespace / packaging 223 : 224 0 : void add_cpp_include(std::string path) { 225 0 : cpp_includes_.push_back(path); 226 0 : } 227 : 228 228 : const std::vector<std::string>& get_cpp_includes() { 229 228 : return cpp_includes_; 230 : } 231 : 232 : void add_c_include(std::string path) { 233 : c_includes_.push_back(path); 234 : } 235 : 236 5 : const std::vector<std::string>& get_c_includes() { 237 5 : return c_includes_; 238 : } 239 : 240 : #ifdef SANDESH 241 538 : t_struct* get_struct(const char *name) const { 242 : // Extract structs, exceptions, or unions matching the name 243 538 : std::vector<t_struct*> objects = get_objects(); 244 538 : std::vector<t_struct*>::iterator o_iter; 245 5000 : for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) { 246 4944 : if (strcmp(((*o_iter)->get_name()).c_str(), name) == 0) { 247 482 : return *o_iter; 248 : } 249 : } 250 56 : return NULL; 251 538 : } 252 : #endif 253 : 254 : private: 255 : 256 : // File path 257 : std::string path_; 258 : 259 : // Name 260 : std::string name_; 261 : 262 : // Output directory 263 : std::string out_path_; 264 : 265 : // Output directory is absolute location for generated source (no gen-*) 266 : bool out_path_is_absolute_; 267 : 268 : // Namespace 269 : std::string namespace_; 270 : 271 : // Included programs 272 : std::vector<t_program*> includes_; 273 : 274 : // Include prefix for this program, if any 275 : std::string include_prefix_; 276 : 277 : // Identifier lookup scope 278 : t_scope* scope_; 279 : 280 : // Components to generate code for 281 : std::vector<t_typedef*> typedefs_; 282 : std::vector<t_enum*> enums_; 283 : std::vector<t_const*> consts_; 284 : std::vector<t_struct*> objects_; 285 : std::vector<t_struct*> structs_; 286 : std::vector<t_struct*> xceptions_; 287 : std::vector<t_service*> services_; 288 : #ifdef SANDESH 289 : std::vector<t_sandesh*> sandeshs_; 290 : #endif 291 : 292 : // Dynamic namespaces 293 : std::map<std::string, std::string> namespaces_; 294 : 295 : // C++ extra includes 296 : std::vector<std::string> cpp_includes_; 297 : 298 : // C extra includes 299 : std::vector<std::string> c_includes_; 300 : 301 : }; 302 : 303 : #endif