@@ -82,3 +82,95 @@ BinaryPlatforms.arch_march_isa_mapping["riscv64"] =
8282 [" riscv64" => get_set (" riscv64" , " riscv64" )]
8383
8484end
85+ function Base. parse (:: Type{Platform} , triplet:: AbstractString ; validate_strict:: Bool = false )
86+ # Helper function to collapse dictionary of mappings down into a regex of
87+ # named capture groups joined by "|" operators
88+ c (mapping) = string (" (" ,join ([" (?<$k >$v )" for (k, v) in mapping], " |" ), " )" )
89+
90+ # We're going to build a mondo regex here to parse everything:
91+ triplet_regex = Regex (string (
92+ " ^" ,
93+ # First, the core triplet; arch/os/libc/call_abi
94+ c (arch_mapping),
95+ c (os_mapping),
96+ c (libc_mapping),
97+ c (call_abi_mapping),
98+ # Next, optional things, like libgfortran/libstdcxx/cxxstring abi
99+ c (libgfortran_version_mapping),
100+ c (cxxstring_abi_mapping),
101+ c (libstdcxx_version_mapping),
102+ # Finally, the catch-all for extended tags
103+ " (?<tags>(?:-[^-]+\\ +[^-]+)*)?" ,
104+ " \$ " ,
105+ ))
106+
107+ m = match (triplet_regex, triplet)
108+ if m != = nothing
109+ # Helper function to find the single named field within the giant regex
110+ # that is not `nothing` for each mapping we give it.
111+ get_field (m, mapping) = begin
112+ for k in keys (mapping)
113+ if m[k] != = nothing
114+ # Convert our sentinel `nothing` values to actual `nothing`
115+ if endswith (k, " _nothing" )
116+ return nothing
117+ end
118+ # Convert libgfortran/libstdcxx version numbers
119+ if startswith (k, " libgfortran" )
120+ return VersionNumber (parse (Int,k[12 : end ]))
121+ elseif startswith (k, " libstdcxx" )
122+ return VersionNumber (3 , 4 , parse (Int,m[k][11 : end ]))
123+ else
124+ return k
125+ end
126+ end
127+ end
128+ end
129+
130+ # Extract the information we're interested in:
131+ arch = get_field (m, arch_mapping)
132+ os = get_field (m, os_mapping)
133+ libc = get_field (m, libc_mapping)
134+ call_abi = get_field (m, call_abi_mapping)
135+ libgfortran_version = get_field (m, libgfortran_version_mapping)
136+ libstdcxx_version = get_field (m, libstdcxx_version_mapping)
137+ cxxstring_abi = get_field (m, cxxstring_abi_mapping)
138+ function split_tags (tagstr)
139+ tag_fields = filter (! isempty, split (tagstr, " -" ))
140+ if isempty (tag_fields)
141+ return Pair{String,String}[]
142+ end
143+ return map (v -> Symbol (v[1 ]) => v[2 ], split .(tag_fields, " +" ))
144+ end
145+ tags = split_tags (m[" tags" ])
146+
147+ # Special parsing of os version number, if any exists
148+ function extract_os_version (os_name, pattern)
149+ m_osvn = match (pattern, m[os_name])
150+ if m_osvn != = nothing
151+ return VersionNumber (m_osvn. captures[1 ])
152+ end
153+ return nothing
154+ end
155+ os_version = nothing
156+ if os == " macos"
157+ os_version = extract_os_version (" macos" , r" .*darwin([\d\. ]+)" )
158+ end
159+ if os == " freebsd"
160+ os_version = extract_os_version (" freebsd" , r" .*freebsd([\d .]+)" )
161+ end
162+
163+ return Platform (
164+ arch, os;
165+ validate_strict,
166+ libc,
167+ call_abi,
168+ libgfortran_version,
169+ cxxstring_abi,
170+ libstdcxx_version,
171+ os_version,
172+ tags... ,
173+ )
174+ end
175+ throw (ArgumentError (" Platform `$(triplet) ` is not an officially supported platform" ))
176+ end
0 commit comments