zeroc-ice 3.8.0 → 3.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. checksums.yaml +4 -4
  2. data/dist/IceRuby/Operation.cpp +22 -6
  3. data/dist/IceRuby/Slice.cpp +1 -1
  4. data/dist/ice/cpp/include/Ice/Communicator.h +4 -4
  5. data/dist/ice/cpp/include/Ice/Config.h +2 -2
  6. data/dist/ice/cpp/include/Ice/Connection.h +3 -3
  7. data/dist/ice/cpp/include/Ice/Endpoint.h +2 -2
  8. data/dist/ice/cpp/include/Ice/Exception.h +1 -1
  9. data/dist/ice/cpp/include/Ice/Initialize.h +1 -1
  10. data/dist/ice/cpp/include/Ice/LocalExceptions.h +22 -1
  11. data/dist/ice/cpp/include/Ice/Logger.h +3 -3
  12. data/dist/ice/cpp/include/Ice/NativePropertiesAdmin.h +2 -0
  13. data/dist/ice/cpp/include/Ice/ObjectAdapter.h +3 -3
  14. data/dist/ice/cpp/include/Ice/ObserverHelper.h +1 -0
  15. data/dist/ice/cpp/include/Ice/OutputStream.h +27 -5
  16. data/dist/ice/cpp/include/Ice/Properties.h +3 -3
  17. data/dist/ice/cpp/include/Ice/Proxy.h +1 -1
  18. data/dist/ice/cpp/include/Ice/SSL/ClientAuthenticationOptions.h +10 -2
  19. data/dist/ice/cpp/include/Ice/SSL/ServerAuthenticationOptions.h +10 -2
  20. data/dist/ice/cpp/include/generated/Ice/BuiltinSequences.h +2 -2
  21. data/dist/ice/cpp/include/generated/Ice/Context.h +2 -2
  22. data/dist/ice/cpp/include/generated/Ice/EndpointTypes.h +2 -2
  23. data/dist/ice/cpp/include/generated/Ice/Identity.h +2 -2
  24. data/dist/ice/cpp/include/generated/Ice/Locator.h +9 -11
  25. data/dist/ice/cpp/include/generated/Ice/LocatorRegistry.h +2 -2
  26. data/dist/ice/cpp/include/generated/Ice/Metrics.h +7 -7
  27. data/dist/ice/cpp/include/generated/Ice/OperationMode.h +2 -2
  28. data/dist/ice/cpp/include/generated/Ice/Process.h +2 -2
  29. data/dist/ice/cpp/include/generated/Ice/PropertiesAdmin.h +2 -2
  30. data/dist/ice/cpp/include/generated/Ice/PropertyDict.h +2 -2
  31. data/dist/ice/cpp/include/generated/Ice/RemoteLogger.h +2 -2
  32. data/dist/ice/cpp/include/generated/Ice/ReplyStatus.h +8 -4
  33. data/dist/ice/cpp/include/generated/Ice/Router.h +7 -7
  34. data/dist/ice/cpp/include/generated/Ice/SliceChecksumDict.h +2 -2
  35. data/dist/ice/cpp/include/generated/Ice/Version.h +2 -2
  36. data/dist/ice/cpp/include/generated/IceDiscovery/Lookup.h +2 -2
  37. data/dist/ice/cpp/include/generated/IceLocatorDiscovery/Lookup.h +2 -2
  38. data/dist/ice/cpp/src/Ice/CollocatedRequestHandler.cpp +5 -3
  39. data/dist/ice/cpp/src/Ice/ConnectionFactory.h +8 -8
  40. data/dist/ice/cpp/src/Ice/ConnectionI.cpp +28 -11
  41. data/dist/ice/cpp/src/Ice/ConnectionI.h +1 -1
  42. data/dist/ice/cpp/src/Ice/Demangle.cpp +1 -0
  43. data/dist/ice/cpp/src/Ice/FileUtil.cpp +3 -67
  44. data/dist/ice/cpp/src/Ice/FileUtil.h +0 -3
  45. data/dist/ice/cpp/src/Ice/IPEndpointI.cpp +4 -0
  46. data/dist/ice/cpp/src/Ice/IncomingRequest.cpp +1 -1
  47. data/dist/ice/cpp/src/Ice/InputStream.cpp +28 -17
  48. data/dist/ice/cpp/src/Ice/LocalException.cpp +1 -1
  49. data/dist/ice/cpp/src/Ice/LocalExceptions.cpp +6 -0
  50. data/dist/ice/cpp/src/Ice/OutgoingAsync.cpp +1 -1
  51. data/dist/ice/cpp/src/Ice/OutgoingResponse.cpp +127 -127
  52. data/dist/ice/cpp/src/Ice/OutgoingResponseInternal.h +21 -0
  53. data/dist/ice/cpp/src/Ice/OutputStream.cpp +80 -115
  54. data/dist/ice/cpp/src/Ice/PropertyNames.cpp +3 -2
  55. data/dist/ice/cpp/src/Ice/ProxyFunctions.cpp +4 -4
  56. data/dist/ice/cpp/src/Ice/Reference.cpp +15 -15
  57. data/dist/ice/cpp/src/Ice/ReferenceFactory.cpp +16 -13
  58. data/dist/ice/cpp/src/Ice/ResourceConfig.h +2 -2
  59. data/dist/ice/cpp/src/Ice/SSL/OpenSSLEngine.cpp +29 -20
  60. data/dist/ice/cpp/src/Ice/SSL/OpenSSLEngine.h +1 -2
  61. data/dist/ice/cpp/src/Ice/SSL/OpenSSLTransceiverI.cpp +14 -3
  62. data/dist/ice/cpp/src/Ice/SSL/RFC2253.cpp +3 -3
  63. data/dist/ice/cpp/src/Ice/SSL/SSLEndpointI.cpp +1 -1
  64. data/dist/ice/cpp/src/Ice/SSL/SSLEngine.h +4 -10
  65. data/dist/ice/cpp/src/Ice/SSL/SSLUtil.cpp +21 -2
  66. data/dist/ice/cpp/src/Ice/SSL/SSLUtil.h +15 -1
  67. data/dist/ice/cpp/src/Ice/SSL/SchannelEngine.cpp +67 -48
  68. data/dist/ice/cpp/src/Ice/SSL/SchannelEngine.h +1 -5
  69. data/dist/ice/cpp/src/Ice/SSL/SchannelTransceiverI.cpp +14 -2
  70. data/dist/ice/cpp/src/Ice/SSL/SecureTransportEngine.cpp +111 -15
  71. data/dist/ice/cpp/src/Ice/SSL/SecureTransportEngine.h +7 -2
  72. data/dist/ice/cpp/src/Ice/SSL/SecureTransportTransceiverI.h +1 -1
  73. data/dist/ice/cpp/src/Ice/SSL/SecureTransportUtil.cpp +3 -16
  74. data/dist/ice/cpp/src/Ice/SSL/TrustManager.cpp +12 -1
  75. data/dist/ice/cpp/src/Ice/ServantManager.h +1 -1
  76. data/dist/ice/cpp/src/Ice/StringConverter.cpp +4 -0
  77. data/dist/ice/cpp/src/Ice/TcpEndpointI.cpp +2 -2
  78. data/dist/ice/cpp/src/Ice/UdpEndpointI.cpp +2 -2
  79. data/dist/ice/cpp/src/Ice/WSAcceptor.cpp +8 -3
  80. data/dist/ice/cpp/src/Ice/WSAcceptor.h +5 -1
  81. data/dist/ice/cpp/src/Ice/WSEndpoint.cpp +45 -2
  82. data/dist/ice/cpp/src/Ice/WSTransceiver.cpp +118 -7
  83. data/dist/ice/cpp/src/Ice/WSTransceiver.h +12 -1
  84. data/dist/ice/cpp/src/Ice/generated/BuiltinSequences.cpp +2 -2
  85. data/dist/ice/cpp/src/Ice/generated/Context.cpp +2 -2
  86. data/dist/ice/cpp/src/Ice/generated/EndpointTypes.cpp +2 -2
  87. data/dist/ice/cpp/src/Ice/generated/Identity.cpp +2 -2
  88. data/dist/ice/cpp/src/Ice/generated/Locator.cpp +2 -2
  89. data/dist/ice/cpp/src/Ice/generated/LocatorRegistry.cpp +2 -2
  90. data/dist/ice/cpp/src/Ice/generated/Metrics.cpp +2 -2
  91. data/dist/ice/cpp/src/Ice/generated/OperationMode.cpp +2 -2
  92. data/dist/ice/cpp/src/Ice/generated/Process.cpp +2 -2
  93. data/dist/ice/cpp/src/Ice/generated/PropertiesAdmin.cpp +2 -2
  94. data/dist/ice/cpp/src/Ice/generated/PropertyDict.cpp +2 -2
  95. data/dist/ice/cpp/src/Ice/generated/RemoteLogger.cpp +2 -2
  96. data/dist/ice/cpp/src/Ice/generated/ReplyStatus.cpp +4 -2
  97. data/dist/ice/cpp/src/Ice/generated/Router.cpp +2 -2
  98. data/dist/ice/cpp/src/Ice/generated/SliceChecksumDict.cpp +2 -2
  99. data/dist/ice/cpp/src/Ice/generated/Version.cpp +2 -2
  100. data/dist/ice/cpp/src/IceDiscovery/LocatorI.cpp +2 -2
  101. data/dist/ice/cpp/src/IceDiscovery/LookupI.cpp +4 -3
  102. data/dist/ice/cpp/src/IceDiscovery/LookupI.h +2 -1
  103. data/dist/ice/cpp/src/IceDiscovery/generated/Lookup.cpp +2 -2
  104. data/dist/ice/cpp/src/IceLocatorDiscovery/PluginI.cpp +6 -18
  105. data/dist/ice/cpp/src/IceLocatorDiscovery/generated/Lookup.cpp +2 -2
  106. data/dist/ice/cpp/src/Slice/DocCommentParser.cpp +6 -6
  107. data/dist/ice/cpp/src/Slice/DocCommentParser.h +4 -2
  108. data/dist/ice/cpp/src/Slice/FileTracker.h +1 -0
  109. data/dist/ice/cpp/src/Slice/Grammar.cpp +261 -264
  110. data/dist/ice/cpp/src/Slice/MetadataValidation.cpp +39 -7
  111. data/dist/ice/cpp/src/Slice/MetadataValidation.h +3 -2
  112. data/dist/ice/cpp/src/Slice/Parser.cpp +192 -155
  113. data/dist/ice/cpp/src/Slice/Parser.h +44 -9
  114. data/dist/ice/cpp/src/Slice/Preprocessor.cpp +76 -20
  115. data/dist/ice/cpp/src/Slice/Preprocessor.h +0 -1
  116. data/dist/ice/cpp/src/Slice/Scanner.cpp +1 -1
  117. data/dist/ice/cpp/src/Slice/SliceUtil.cpp +44 -58
  118. data/dist/ice/cpp/src/Slice/StringLiteralUtil.cpp +3 -10
  119. data/dist/ice/cpp/src/Slice/Util.h +7 -3
  120. data/dist/ice/cpp/src/slice2rb/Main.cpp +2 -2
  121. data/dist/ice/cpp/src/slice2rb/Ruby.cpp +1 -1
  122. data/dist/ice/cpp/src/slice2rb/RubyUtil.cpp +10 -8
  123. data/dist/ice/cpp/src/slice2rb/RubyUtil.h +10 -13
  124. data/dist/ice/mcpp/directive.c +5 -2
  125. data/dist/ice/mcpp/mcpp_main.c +1 -1
  126. data/dist/ice/mcpp/support.c +6 -6
  127. data/dist/ice/mcpp/system.c +5 -5
  128. data/dist/ice/slice/Ice/Identity.ice +3 -0
  129. data/dist/ice/slice/Ice/Locator.ice +6 -5
  130. data/dist/ice/slice/Ice/LocatorRegistry.ice +3 -0
  131. data/dist/ice/slice/Ice/Metrics.ice +1 -1
  132. data/dist/ice/slice/Ice/OperationMode.ice +8 -0
  133. data/dist/ice/slice/Ice/Process.ice +3 -0
  134. data/dist/ice/slice/Ice/ReplyStatus.ice +13 -0
  135. data/dist/lib/Glacier2/Metrics.rb +1 -1
  136. data/dist/lib/Glacier2/PermissionsVerifier.rb +3 -3
  137. data/dist/lib/Glacier2/Router.rb +8 -8
  138. data/dist/lib/Glacier2/SSLInfo.rb +1 -1
  139. data/dist/lib/Glacier2/Session.rb +15 -15
  140. data/dist/lib/Ice/BuiltinSequences.rb +1 -1
  141. data/dist/lib/Ice/Context.rb +1 -1
  142. data/dist/lib/Ice/EndpointTypes.rb +1 -1
  143. data/dist/lib/Ice/Identity.rb +1 -1
  144. data/dist/lib/Ice/LocalExceptions.rb +3 -0
  145. data/dist/lib/Ice/Locator.rb +5 -5
  146. data/dist/lib/Ice/LocatorRegistry.rb +4 -4
  147. data/dist/lib/Ice/Metrics.rb +7 -7
  148. data/dist/lib/Ice/OperationMode.rb +1 -1
  149. data/dist/lib/Ice/Process.rb +3 -3
  150. data/dist/lib/Ice/PropertiesAdmin.rb +4 -4
  151. data/dist/lib/Ice/PropertyDict.rb +1 -1
  152. data/dist/lib/Ice/ProxyFunctions.rb +8 -4
  153. data/dist/lib/Ice/RemoteLogger.rb +6 -6
  154. data/dist/lib/Ice/ReplyStatus.rb +3 -2
  155. data/dist/lib/Ice/Router.rb +5 -5
  156. data/dist/lib/Ice/SliceChecksumDict.rb +1 -1
  157. data/dist/lib/Ice/Version.rb +1 -1
  158. data/dist/lib/IceBox/ServiceManager.rb +8 -8
  159. data/dist/lib/IceGrid/Admin.rb +83 -83
  160. data/dist/lib/IceGrid/Descriptor.rb +1 -1
  161. data/dist/lib/IceGrid/Exception.rb +1 -1
  162. data/dist/lib/IceGrid/FileParser.rb +2 -2
  163. data/dist/lib/IceGrid/Registry.rb +13 -13
  164. data/dist/lib/IceGrid/Session.rb +6 -6
  165. data/dist/lib/IceGrid/UserAccountMapper.rb +2 -2
  166. data/dist/lib/IceStorm/IceStorm.rb +16 -16
  167. data/dist/lib/IceStorm/Metrics.rb +1 -1
  168. data/ice.gemspec +1 -1
  169. metadata +2 -1
@@ -6,6 +6,7 @@
6
6
  #include <array>
7
7
  #include <cstdint>
8
8
  #include <functional>
9
+ #include <limits>
9
10
  #include <list>
10
11
  #include <map>
11
12
  #include <memory>
@@ -390,6 +391,10 @@ namespace Slice
390
391
  /// Returns the mapped identifier that this element will use in the target language.
391
392
  [[nodiscard]] std::string mappedName() const;
392
393
 
394
+ /// Returns the mapped name for this element in the target language if it has been customized with the
395
+ /// 'lang:name' metadata, or `nullopt` if it doesn't have a custom name.
396
+ [[nodiscard]] std::optional<std::string> customMappedName() const;
397
+
393
398
  /// Returns the mapped fully-scoped identifier that this element will use in the target language.
394
399
  /// @param separator This string will be used to separate scope segments.
395
400
  /// @param leading If true, the returned string will have a leading `separator` (defaults to false).
@@ -476,8 +481,8 @@ namespace Slice
476
481
  MetadataList metadata,
477
482
  const SyntaxTreeBasePtr& valueType,
478
483
  const std::string& value);
479
- [[nodiscard]] TypeList lookupType(const std::string& identifier);
480
- [[nodiscard]] TypeList
484
+ [[nodiscard]] TypePtr lookupType(const std::string& identifier);
485
+ [[nodiscard]] TypePtr
481
486
  lookupTypeNoBuiltin(const std::string& identifier, bool emitErrors, bool ignoreUndefined = false);
482
487
  [[nodiscard]] ContainedList lookupContained(const std::string& identifier, bool emitErrors);
483
488
  [[nodiscard]] InterfaceDefPtr lookupInterfaceDef(const std::string& identifier, bool emitErrors);
@@ -687,8 +692,15 @@ namespace Slice
687
692
  Idempotent = 2
688
693
  };
689
694
 
690
- Operation(const ContainerPtr&, const std::string&, TypePtr, bool, std::int32_t, Mode);
691
- [[nodiscard]] InterfaceDefPtr interface() const;
695
+ Operation(
696
+ const ContainerPtr& container,
697
+ const std::string& name,
698
+ TypePtr returnType,
699
+ bool returnIsOptional,
700
+ std::int32_t returnTag,
701
+ Mode mode);
702
+
703
+ [[nodiscard]] InterfaceDefPtr parentInterface() const;
692
704
  [[nodiscard]] TypePtr returnType() const;
693
705
  [[nodiscard]] bool returnIsOptional() const;
694
706
  [[nodiscard]] std::int32_t returnTag() const;
@@ -735,12 +747,19 @@ namespace Slice
735
747
 
736
748
  [[nodiscard]] ExceptionList throws() const;
737
749
  void setExceptionList(const ExceptionList& exceptions);
750
+
751
+ /// Returns true if this operation uses class types in any of its in parameters.
738
752
  [[nodiscard]] bool sendsClasses() const;
753
+
754
+ /// Returns true if this operation uses class types in its return type, or any of its out parameters.
739
755
  [[nodiscard]] bool returnsClasses() const;
756
+
757
+ /// Returns true if this operation has any out parameters, a non-void return type, or can throw any exceptions.
740
758
  [[nodiscard]] bool returnsData() const;
741
759
 
742
760
  /// Returns true if this operation has any out parameters or a non-void return type.
743
761
  [[nodiscard]] bool returnsAnyValues() const;
762
+
744
763
  /// Returns true if this operation's output parameters, plus any non-void return type, is greater than 1.
745
764
  [[nodiscard]] bool returnsMultipleValues() const;
746
765
 
@@ -787,6 +806,7 @@ namespace Slice
787
806
  [[nodiscard]] InterfaceList allBases() const;
788
807
  [[nodiscard]] OperationList operations() const;
789
808
  [[nodiscard]] OperationList allOperations() const;
809
+ [[nodiscard]] OperationList allInheritedOperations() const;
790
810
  [[nodiscard]] std::string kindOf() const final;
791
811
  void visit(ParserVisitor* visitor) final;
792
812
 
@@ -943,7 +963,7 @@ namespace Slice
943
963
 
944
964
  private:
945
965
  bool _hasExplicitValues{false};
946
- std::int32_t _minValue;
966
+ std::int32_t _minValue{std::numeric_limits<std::int32_t>::max()};
947
967
  std::int32_t _maxValue{0};
948
968
  std::int32_t _lastValue{-1};
949
969
  };
@@ -1014,9 +1034,10 @@ namespace Slice
1014
1034
  [[nodiscard]] TypePtr type() const;
1015
1035
  [[nodiscard]] bool isOutParam() const;
1016
1036
  void setIsOutParam();
1017
- [[nodiscard]] bool optional() const;
1037
+ [[nodiscard]] bool isOptional() const;
1018
1038
  [[nodiscard]] std::int32_t tag() const;
1019
1039
  [[nodiscard]] std::string kindOf() const final;
1040
+
1020
1041
  void visit(ParserVisitor* visitor) final;
1021
1042
 
1022
1043
  private:
@@ -1042,13 +1063,14 @@ namespace Slice
1042
1063
  SyntaxTreeBasePtr defaultValueType,
1043
1064
  std::optional<std::string> defaultValueString);
1044
1065
  [[nodiscard]] TypePtr type() const;
1045
- [[nodiscard]] bool optional() const;
1066
+ [[nodiscard]] bool isOptional() const;
1046
1067
  [[nodiscard]] std::int32_t tag() const;
1047
1068
 
1048
1069
  // defaultValue() and defaultValueType() are either both null (no default value) or both non-null.
1049
1070
  [[nodiscard]] std::optional<std::string> defaultValue() const;
1050
1071
  [[nodiscard]] SyntaxTreeBasePtr defaultValueType() const;
1051
1072
  [[nodiscard]] std::string kindOf() const final;
1073
+
1052
1074
  void visit(ParserVisitor* visitor) final;
1053
1075
 
1054
1076
  private:
@@ -1063,14 +1085,26 @@ namespace Slice
1063
1085
  // Unit
1064
1086
  // ----------------------------------------------------------------------
1065
1087
 
1088
+ /// Options for creating a Unit.
1089
+ struct UnitOptions
1090
+ {
1091
+ /// When true, generate code for Slice definitions in included files.
1092
+ bool all{false};
1093
+
1094
+ /// Provides a function that returns the default mapped name for a Contained element. nullptr, the default,
1095
+ /// is equivalent to using the element's Slice name as its mapped name.
1096
+ std::function<std::string(const Contained&)> defaultMappedName{nullptr};
1097
+ };
1098
+
1066
1099
  class Unit final : public Container
1067
1100
  {
1068
1101
  public:
1069
- static UnitPtr createUnit(std::string languageName, bool all);
1102
+ static UnitPtr createUnit(std::string languageName, UnitOptions options = {});
1070
1103
 
1071
- Unit(std::string languageName, bool all);
1104
+ Unit(std::string languageName, UnitOptions options);
1072
1105
 
1073
1106
  [[nodiscard]] std::string languageName() const;
1107
+ [[nodiscard]] std::string defaultMappedName(const Contained& contained) const;
1074
1108
 
1075
1109
  /// Sets `_currentDocComment` to the provided string, erasing anything currently stored in it.
1076
1110
  /// @param comment The raw comment string. It can span multiple lines and include comment formatting characters
@@ -1154,6 +1188,7 @@ namespace Slice
1154
1188
 
1155
1189
  const std::string _languageName;
1156
1190
  bool _all;
1191
+ std::function<std::string(const Contained&)> _defaultMappedName;
1157
1192
  int _errors{0};
1158
1193
  std::string _currentDocComment;
1159
1194
  int _currentIncludeLevel{0};
@@ -9,21 +9,80 @@
9
9
  #include "Util.h"
10
10
  #include <algorithm>
11
11
  #include <cassert>
12
+ #include <cerrno>
12
13
  #include <cstring>
14
+ #include <fcntl.h>
13
15
  #include <fstream>
14
16
  #include <iterator>
15
17
  #include <sys/stat.h>
16
18
  #include <sys/types.h>
17
19
  #include <vector>
18
20
 
19
- #ifndef _WIN32
21
+ #ifdef _WIN32
22
+ # include <io.h>
23
+ # include <share.h>
24
+ #else
20
25
  # include <sys/wait.h>
26
+ # include <unistd.h>
21
27
  #endif
22
28
 
23
29
  using namespace std;
24
30
  using namespace Slice;
25
31
  using namespace IceInternal;
26
32
 
33
+ namespace
34
+ {
35
+ // Atomically create and open a new file for read/write, failing if the file already exists or, on POSIX, if the
36
+ // path resolves to a symlink. This avoids the TOCTOU race that a name-then-open sequence would otherwise expose
37
+ // to a local attacker who could plant a symlink at the generated path.
38
+ #ifdef _WIN32
39
+ FILE* openExclusive(const wchar_t* path)
40
+ {
41
+ int fd = -1;
42
+ // _O_TEMPORARY tells the CRT to delete the file when the last file descriptor is closed -- this avoids the
43
+ // need for a separate, racy unlink-by-name in close().
44
+ if (::_wsopen_s(
45
+ &fd,
46
+ path,
47
+ _O_RDWR | _O_CREAT | _O_EXCL | _O_BINARY | _O_TEMPORARY,
48
+ _SH_DENYRW,
49
+ _S_IREAD | _S_IWRITE) != 0)
50
+ {
51
+ return nullptr;
52
+ }
53
+ FILE* fp = ::_fdopen(fd, "w+");
54
+ if (!fp)
55
+ {
56
+ ::_close(fd);
57
+ }
58
+ return fp;
59
+ }
60
+ #else
61
+ FILE* openExclusive(const char* path)
62
+ {
63
+ int fd = ::open(path, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, S_IRUSR | S_IWUSR);
64
+ if (fd == -1)
65
+ {
66
+ return nullptr;
67
+ }
68
+ // Unlink immediately so the file is anonymous: the inode survives via our descriptor and the kernel
69
+ // releases it on close. ENOENT means another process already removed the entry, leaving us in the same
70
+ // state; any other unlink error is fatal because the caller has no path to retry cleanup.
71
+ if (::unlink(path) != 0 && errno != ENOENT)
72
+ {
73
+ ::close(fd);
74
+ return nullptr;
75
+ }
76
+ FILE* fp = ::fdopen(fd, "w+");
77
+ if (!fp)
78
+ {
79
+ ::close(fd);
80
+ }
81
+ return fp;
82
+ }
83
+ #endif
84
+ }
85
+
27
86
  //
28
87
  // mcpp defines
29
88
  //
@@ -86,7 +145,7 @@ Slice::Preprocessor::normalizeIncludePath(const string& path)
86
145
  //
87
146
  // MCPP does not handle "-IC:/" well as an include path.
88
147
  //
89
- if (path.size() != 3 || !(path[0] >= 'A' && path[0] <= 'Z') || (path[0] >= 'a' && path[0] <= 'z') ||
148
+ if (path.size() != 3 || !((path[0] >= 'A' && path[0] <= 'Z') || (path[0] >= 'a' && path[0] <= 'z')) ||
90
149
  path[1] != ':' || path[2] != '\\')
91
150
  #endif
92
151
  {
@@ -201,32 +260,32 @@ Slice::Preprocessor::preprocess(const string& languageArg)
201
260
  //
202
261
  #ifdef _WIN32
203
262
  //
204
- // We use an unique id as the tmp file name prefix to avoid
205
- // problems with this code being called concurrently from
206
- // several processes, otherwise there is a change that two
207
- // process call _tempnam before any of them call fopen and
208
- // they will end up using the same tmp file.
263
+ // We use an unique id as the tmp file name prefix to avoid problems with this code being called concurrently
264
+ // from several processes, otherwise there is a chance that two processes call _wtempnam before any of them
265
+ // opens the file and they will end up using the same tmp file. We then open the file with O_EXCL to atomically
266
+ // create it -- this closes the TOCTOU window between _wtempnam returning a name and our opening it. The
267
+ // _O_TEMPORARY flag inside openExclusive causes the file to be deleted automatically when the descriptor is
268
+ // closed, so we don't need to retain the path past this point.
209
269
  //
210
270
  wchar_t* name = _wtempnam(0, Ice::stringToWstring("slice-" + Ice::generateUUID()).c_str());
211
271
  if (name)
212
272
  {
213
- _cppFile = Ice::wstringToString(name);
273
+ _cppHandle = openExclusive(name);
214
274
  free(name);
215
- _cppHandle = IceInternal::fopen(_cppFile, "w+");
216
275
  }
217
276
  #else
218
277
  _cppHandle = tmpfile();
219
278
  #endif
220
279
 
221
- // If that fails try to open file in current directory.
280
+ // If that fails try to open file in current directory. openExclusive immediately unlinks the file on POSIX
281
+ // and sets _O_TEMPORARY on Windows, so the path is only used during the open attempt.
222
282
  if (_cppHandle == nullptr)
223
283
  {
224
284
  #ifdef _WIN32
225
- _cppFile = "slice-" + Ice::generateUUID();
285
+ _cppHandle = openExclusive(Ice::stringToWstring("slice-" + Ice::generateUUID()).c_str());
226
286
  #else
227
- _cppFile = ".slice-" + Ice::generateUUID();
287
+ _cppHandle = openExclusive((".slice-" + Ice::generateUUID()).c_str());
228
288
  #endif
229
- _cppHandle = IceInternal::fopen(_cppFile, "w+");
230
289
  }
231
290
 
232
291
  if (_cppHandle != nullptr)
@@ -241,7 +300,7 @@ Slice::Preprocessor::preprocess(const string& languageArg)
241
300
  {
242
301
  // Calling this again causes the memory buffers to be freed.
243
302
  mcpp_use_mem_buffers(1);
244
- throw runtime_error(_path + ": error: could not open temporary file: " + _cppFile);
303
+ throw runtime_error(_path + ": error: could not open temporary file for preprocessor output");
245
304
  }
246
305
  }
247
306
 
@@ -256,14 +315,11 @@ Slice::Preprocessor::close()
256
315
  {
257
316
  if (_cppHandle != nullptr)
258
317
  {
318
+ // The temp file deletes itself when the descriptor is closed. On POSIX, tmpfile() returns an
319
+ // already-unlinked file and the CWD fallback unlinks after open; on Windows, openExclusive opens
320
+ // with _O_TEMPORARY. fclose is the only cleanup needed.
259
321
  int status = fclose(_cppHandle);
260
322
  _cppHandle = nullptr;
261
-
262
- if (_cppFile.size() != 0)
263
- {
264
- IceInternal::unlink(_cppFile);
265
- }
266
-
267
323
  if (status != 0)
268
324
  {
269
325
  throw runtime_error("failed to close preprocessor file: " + IceInternal::lastErrorToString());
@@ -36,7 +36,6 @@ namespace Slice
36
36
  const std::string _fileName;
37
37
  const std::string _shortFileName;
38
38
  const std::vector<std::string> _args;
39
- std::string _cppFile;
40
39
  FILE* _cppHandle{nullptr};
41
40
  };
42
41
  }
@@ -1895,7 +1895,7 @@ YY_RULE_SETUP
1895
1895
  {
1896
1896
  literal = literal.substr(0, literal.size() - 1); // Clobber trailing 'f' or 'F' suffix
1897
1897
  }
1898
- ftp->v = strtod(literal.c_str(), 0);
1898
+ ftp->v = strtod(literal.c_str(), nullptr);
1899
1899
  if ((ftp->v == HUGE_VAL || ftp->v == -HUGE_VAL) && errno == ERANGE)
1900
1900
  {
1901
1901
  currentUnit->error("floating-point constant '" + string{yytext} + "' too large (overflow)");
@@ -7,6 +7,7 @@
7
7
  #include "Util.h"
8
8
  #include <algorithm>
9
9
  #include <cassert>
10
+ #include <cctype>
10
11
  #include <climits>
11
12
  #include <cstring>
12
13
 
@@ -239,6 +240,43 @@ Slice::dirName(const string& path)
239
240
  }
240
241
  }
241
242
 
243
+ string
244
+ Slice::toPascalCase(const string& s)
245
+ {
246
+ string result;
247
+ result.reserve(s.size());
248
+ bool capitalizeNext = true;
249
+ for (char c : s)
250
+ {
251
+ if (c == '_')
252
+ {
253
+ capitalizeNext = true;
254
+ // and consume this underscore
255
+ }
256
+ else if (capitalizeNext)
257
+ {
258
+ result += static_cast<char>(toupper(static_cast<unsigned char>(c)));
259
+ capitalizeNext = false;
260
+ }
261
+ else
262
+ {
263
+ result += c;
264
+ }
265
+ }
266
+ return result;
267
+ }
268
+
269
+ string
270
+ Slice::toCamelCase(const string& s)
271
+ {
272
+ string result = toPascalCase(s);
273
+ if (!result.empty())
274
+ {
275
+ result[0] = static_cast<char>(tolower(static_cast<unsigned char>(result[0])));
276
+ }
277
+ return result;
278
+ }
279
+
242
280
  void
243
281
  Slice::emitError(string_view file, int line, string_view message)
244
282
  {
@@ -451,7 +489,7 @@ Slice::getArticleFor(const string& s)
451
489
  return (vowels.find_first_of(s[0]) != string::npos) ? "an" : "a";
452
490
  }
453
491
 
454
- std::string
492
+ string
455
493
  Slice::pluralKindOf(const ContainedPtr& p)
456
494
  {
457
495
  string kindOf = p->kindOf();
@@ -469,58 +507,6 @@ Slice::pluralKindOf(const ContainedPtr& p)
469
507
  }
470
508
  }
471
509
 
472
- bool
473
- Slice::reportIllegalSuffixOrUnderscore(const string& identifier)
474
- {
475
- // check whether the identifier is scoped
476
- size_t scopeIndex = identifier.rfind("::");
477
- bool isScoped = scopeIndex != string::npos;
478
- string name;
479
- if (isScoped)
480
- {
481
- name = identifier.substr(scopeIndex + 2); // Only check the unscoped identifier for syntax
482
- }
483
- else
484
- {
485
- name = identifier;
486
- }
487
-
488
- assert(!name.empty());
489
- bool isValid = true;
490
-
491
- // check the identifier for reserved suffixes
492
- static const string suffixBlacklist[] = {"Helper", "Holder", "Prx", "Ptr"};
493
- for (const auto& i : suffixBlacklist)
494
- {
495
- if (name.find(i, name.size() - i.size()) != string::npos)
496
- {
497
- currentUnit->error("illegal identifier '" + name + "': '" + i + "' suffix is reserved");
498
- isValid = false;
499
- break;
500
- }
501
- }
502
-
503
- // check the identifier for illegal underscores
504
- size_t index = name.find('_');
505
- if (index == 0)
506
- {
507
- currentUnit->error("illegal leading underscore in identifier '" + name + "'");
508
- isValid = false;
509
- }
510
- else if (name.rfind('_') == (name.size() - 1))
511
- {
512
- currentUnit->error("illegal trailing underscore in identifier '" + name + "'");
513
- isValid = false;
514
- }
515
- else if (name.find("__") != string::npos)
516
- {
517
- currentUnit->error("illegal double underscore in identifier '" + name + "'");
518
- isValid = false;
519
- }
520
-
521
- return isValid;
522
- }
523
-
524
510
  bool
525
511
  Slice::isProxyType(const TypePtr& type)
526
512
  {
@@ -597,7 +583,7 @@ Slice::getFirstSentence(const StringList& lines)
597
583
  }
598
584
 
599
585
  string
600
- Slice::getEscapedParamName(const ParameterList& params, std::string_view param)
586
+ Slice::getEscapedParamName(const ParameterList& params, string_view param)
601
587
  {
602
588
  for (const auto& p : params)
603
589
  {
@@ -612,14 +598,14 @@ Slice::getEscapedParamName(const ParameterList& params, std::string_view param)
612
598
  string
613
599
  Slice::getTypeScopedName(const TypePtr& type)
614
600
  {
615
- if (auto builtin = std::dynamic_pointer_cast<Builtin>(type))
601
+ if (auto builtin = dynamic_pointer_cast<Builtin>(type))
616
602
  {
617
603
  return builtin->kindAsString();
618
604
  }
619
605
  else
620
606
  {
621
607
  // a type is either built-in or contained
622
- auto contained = std::dynamic_pointer_cast<Contained>(type);
608
+ auto contained = dynamic_pointer_cast<Contained>(type);
623
609
  assert(contained);
624
610
  return contained->scoped();
625
611
  }
@@ -717,7 +703,7 @@ Slice::DependencyGenerator::writeMakefileDependencies(
717
703
  }
718
704
 
719
705
  void
720
- Slice::DependencyGenerator::writeXMLDependencies(const std::string& dependFile)
706
+ Slice::DependencyGenerator::writeXMLDependencies(const string& dependFile)
721
707
  {
722
708
  ostringstream os;
723
709
  os << R"(<?xml version="1.0" encoding="UTF-8"?>)";
@@ -739,7 +725,7 @@ Slice::DependencyGenerator::writeXMLDependencies(const std::string& dependFile)
739
725
  }
740
726
 
741
727
  void
742
- Slice::DependencyGenerator::writeJSONDependencies(const std::string& dependFile)
728
+ Slice::DependencyGenerator::writeJSONDependencies(const string& dependFile)
743
729
  {
744
730
  ostringstream os;
745
731
  os << "{";
@@ -48,21 +48,14 @@ namespace
48
48
  EscapeMode escapeMode,
49
49
  unsigned char cutOff)
50
50
  : _nonPrintableEscaped(std::move(nonPrintableEscaped)),
51
- _printableEscaped(printableEscaped + "\\"),
51
+ // Double quotes don't need to be escaped in Matlab because the string delimiter is a single quote.
52
+ _printableEscaped(printableEscaped + "\\" + (escapeMode != Matlab ? "\"" : "")),
52
53
  _escapeMode(escapeMode),
53
54
  _cutOff(cutOff),
54
55
  _shortUCNPrefix(escapeMode == Matlab ? "\\x" : "\\u"),
55
56
  _octalChars("01234567"),
56
- _hexChars("01234567890ABCDEFabcdef")
57
-
57
+ _hexChars("0123456789ABCDEFabcdef")
58
58
  {
59
- //
60
- // Double quotes don't need to be escaped in Matlab because the string delimiter is a single quote.
61
- //
62
- if (_escapeMode != Matlab)
63
- {
64
- const_cast<string&>(_printableEscaped) += '"';
65
- }
66
59
  }
67
60
 
68
61
  string StringLiteralGenerator::escapeASCIIChar(char c)
@@ -14,6 +14,13 @@ namespace Slice
14
14
  std::string removeExtension(const std::string& path);
15
15
  std::string baseName(const std::string& path);
16
16
  std::string dirName(const std::string& path);
17
+
18
+ /// Converts a string to Pascal case. For example, "myClass" becomes "MyClass".
19
+ std::string toPascalCase(const std::string& s);
20
+
21
+ /// Converts a string to camel case. For example, "MyClass" becomes "myClass".
22
+ std::string toCamelCase(const std::string& s);
23
+
17
24
  void emitError(std::string_view file, int line, std::string_view message);
18
25
  void emitWarning(std::string_view file, int line, std::string_view message);
19
26
  void emitRaw(const char* message);
@@ -63,9 +70,6 @@ namespace Slice
63
70
  /// @see Contained::kindOf
64
71
  std::string pluralKindOf(const ContainedPtr& p);
65
72
 
66
- // Checks an identifier for illegal syntax and reports any errors that are present.
67
- bool reportIllegalSuffixOrUnderscore(const std::string& identifier);
68
-
69
73
  bool isProxyType(const TypePtr& type);
70
74
 
71
75
  // Is this the first element defined in its container?
@@ -22,12 +22,12 @@ main(int argc, char* argv[])
22
22
  }
23
23
  catch (const std::exception& ex)
24
24
  {
25
- consoleErr << args[0] << ": error:" << ex.what() << endl;
25
+ consoleErr << args[0] << ": error: " << ex.what() << endl;
26
26
  return EXIT_FAILURE;
27
27
  }
28
28
  catch (...)
29
29
  {
30
- consoleErr << args[0] << ": error:unknown exception" << endl;
30
+ consoleErr << args[0] << ": error: unknown exception" << endl;
31
31
  return EXIT_FAILURE;
32
32
  }
33
33
  }
@@ -156,7 +156,7 @@ Slice::Ruby::compile(const vector<string>& argv)
156
156
  return EXIT_FAILURE;
157
157
  }
158
158
 
159
- unit = Unit::createUnit("ruby", all);
159
+ unit = Unit::createUnit("ruby", {.all = all});
160
160
  int parseStatus = unit->parse(fileName, preprocessedHandle, debug);
161
161
 
162
162
  preprocessor->close();
@@ -241,13 +241,14 @@ Slice::Ruby::CodeVisitor::visitClassDefStart(const ClassDefPtr& p)
241
241
  }
242
242
  for (auto q = members.begin(); q != members.end(); ++q)
243
243
  {
244
+ const bool isOptional = (*q)->isOptional();
244
245
  if (q != members.begin())
245
246
  {
246
247
  _out << ',' << nl;
247
248
  }
248
249
  _out << "['" << getMappedName(*q) << "', ";
249
250
  writeType((*q)->type());
250
- _out << ", " << ((*q)->optional() ? "true" : "false") << ", " << ((*q)->optional() ? (*q)->tag() : 0) << ']';
251
+ _out << ", " << (isOptional ? "true" : "false") << ", " << (isOptional ? (*q)->tag() : 0) << ']';
251
252
  }
252
253
  if (members.size() > 1)
253
254
  {
@@ -407,6 +408,7 @@ Slice::Ruby::CodeVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p)
407
408
  bool isFirst = true;
408
409
  for (const auto& param : op->inParameters())
409
410
  {
411
+ const bool isOptional = param->isOptional();
410
412
  if (!isFirst)
411
413
  {
412
414
  _out << ", ";
@@ -414,13 +416,13 @@ Slice::Ruby::CodeVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p)
414
416
  isFirst = false;
415
417
  _out << '[';
416
418
  writeType(param->type());
417
- _out << ", " << (param->optional() ? "true" : "false") << ", " << (param->optional() ? param->tag() : 0)
418
- << ']';
419
+ _out << ", " << (isOptional ? "true" : "false") << ", " << (isOptional ? param->tag() : 0) << ']';
419
420
  }
420
421
  _out << "], [";
421
422
  isFirst = true;
422
423
  for (const auto& param : op->outParameters())
423
424
  {
425
+ const bool isOptional = param->isOptional();
424
426
  if (!isFirst)
425
427
  {
426
428
  _out << ", ";
@@ -428,8 +430,7 @@ Slice::Ruby::CodeVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p)
428
430
  isFirst = false;
429
431
  _out << '[';
430
432
  writeType(param->type());
431
- _out << ", " << (param->optional() ? "true" : "false") << ", " << (param->optional() ? param->tag() : 0)
432
- << ']';
433
+ _out << ", " << (isOptional ? "true" : "false") << ", " << (isOptional ? param->tag() : 0) << ']';
433
434
  }
434
435
  _out << "], ";
435
436
  TypePtr returnType = op->returnType();
@@ -456,6 +457,7 @@ Slice::Ruby::CodeVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p)
456
457
  _out << getMetaTypeReference(ex);
457
458
  }
458
459
  _out.epar("]");
460
+ _out << ", " << (op->hasMetadata("oneway") ? "true" : "false");
459
461
  _out << ")";
460
462
 
461
463
  if (op->isDeprecated())
@@ -547,14 +549,14 @@ Slice::Ruby::CodeVisitor::visitExceptionStart(const ExceptionPtr& p)
547
549
  //
548
550
  for (auto dmli = members.begin(); dmli != members.end(); ++dmli)
549
551
  {
552
+ const bool isOptional = (*dmli)->isOptional();
550
553
  if (dmli != members.begin())
551
554
  {
552
555
  _out << ',' << nl;
553
556
  }
554
557
  _out << "[\"" << getMappedName(*dmli) << "\", ";
555
558
  writeType((*dmli)->type());
556
- _out << ", " << ((*dmli)->optional() ? "true" : "false") << ", " << ((*dmli)->optional() ? (*dmli)->tag() : 0)
557
- << ']';
559
+ _out << ", " << (isOptional ? "true" : "false") << ", " << (isOptional ? (*dmli)->tag() : 0) << ']';
558
560
  }
559
561
  if (members.size() > 1)
560
562
  {
@@ -1038,7 +1040,7 @@ Slice::Ruby::CodeVisitor::writeConstructorParams(const DataMemberList& members)
1038
1040
  {
1039
1041
  writeConstantValue(member->type(), member->defaultValueType(), *member->defaultValue());
1040
1042
  }
1041
- else if (member->optional())
1043
+ else if (member->isOptional())
1042
1044
  {
1043
1045
  _out << "Ice::Unset";
1044
1046
  }