yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
f65d756bf
master
1#include "slang-command-line-args.h" 2 3#include "../core/slang-process-util.h" 4#include "../core/slang-string-escape-util.h" 5#include "../core/slang-string-util.h" 6#include "../core/slang-type-text-util.h" 7#include "slang-core-diagnostics.h" 8 9namespace Slang 10{ 11 12void CommandLineArgs ::setArgs (const char * const * args ,size_t argCount ) 13{ 14m_args .clear (); 15 16SourceManager * sourceManager = m_context -> getSourceManager (); 17 18const SourceLoc startLoc = sourceManager -> getNextRangeStart (); 19 20StringBuilder buf ; 21 22auto escapeHandler = Process ::getEscapeHandler (); 23 24for (size_t i = 0 ;i < argCount ;++ i ) 25 { 26const Index offset = buf .getLength (); 27 28const char * srcArg = args [i ]; 29 30Arg dstArg ; 31dstArg .loc = startLoc + offset ; 32dstArg .value = srcArg ; 33 34m_args .add (dstArg ); 35 36// Write the string escaped if necessary 37StringEscapeUtil ::appendMaybeQuoted (escapeHandler ,dstArg .value .getUnownedSlice (),buf ); 38 39// Put a space between the args 40buf <<" " ; 41 } 42 43SourceFile * sourceFile = 44sourceManager -> createSourceFileWithString (PathInfo ::makeUnknown (),buf .produceString ()); 45SourceView * sourceView = 46sourceManager -> createSourceView (sourceFile ,nullptr ,SourceLoc ::fromRaw (0 )); 47 48SLANG_UNUSED (sourceView ); 49SLANG_ASSERT (sourceView -> getRange ().begin == startLoc ); 50} 51 52bool CommandLineArgs ::hasArgs (const char * const * args ,Index count )const 53{ 54if (m_args .getCount ()!= count ) 55 { 56return false; 57 } 58 59for (Index i = 0 ;i < count ;++ i ) 60 { 61if (m_args [i ].value != args [i ]) 62 { 63return false; 64 } 65 } 66 67return true; 68} 69 70String CommandLineArgs ::serialize () 71{ 72StringBuilder sb ; 73for (auto & arg :m_args ) 74sb <<arg .value <<"\n" ; 75return sb .produceString (); 76} 77 78void CommandLineArgs ::deserialize (String content ) 79{ 80List < UnownedStringSlice > slices ; 81StringUtil ::split (content .getUnownedSlice (),'\n' ,slices ); 82for (auto arg :slices ) 83 { 84Arg v ; 85v .value = arg ; 86v .loc = SourceLoc (); 87m_args .add (v ); 88 } 89} 90 91/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 92 93CommandLineReader 94 95!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ 96 97String CommandLineReader ::getPreviousValue ()const 98{ 99SLANG_ASSERT (m_index > 0 ); 100if (m_index > 0 ) 101 { 102const auto & prevArg = (* m_args )[m_index - 1 ]; 103return prevArg .value ; 104 } 105else 106 { 107return String (); 108 } 109} 110 111SlangResult CommandLineReader ::expectArg (String & outArg ) 112{ 113if (hasArg ()) 114 { 115outArg = m_args -> m_args [m_index ++ ].value ; 116return SLANG_OK ; 117 } 118else 119 { 120m_sink -> diagnose (peekLoc (),MiscDiagnostics ::expectedArgumentForOption ,getPreviousValue ()); 121return SLANG_FAIL ; 122 } 123} 124 125SlangResult CommandLineReader ::expectArg (CommandLineArg & outArg ) 126{ 127if (hasArg ()) 128 { 129outArg = peekArg (); 130advance (); 131return SLANG_OK ; 132 } 133else 134 { 135m_sink -> diagnose (peekLoc (),MiscDiagnostics ::expectedArgumentForOption ,getPreviousValue ()); 136return SLANG_FAIL ; 137 } 138} 139 140/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 141 142DownstreamArgs 143 144!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ 145 146DownstreamArgs ::DownstreamArgs (CommandLineContext * context ) 147 :m_context (context ) 148{ 149// Add all of the possible names we allow for downstream tools 150 { 151for (Index i = SLANG_PASS_THROUGH_NONE + 1 ;i < SLANG_PASS_THROUGH_COUNT_OF ;++ i ) 152 { 153addName (TypeTextUtil ::getPassThroughName (SlangPassThrough (i ))); 154 } 155 156// Generic downstream tool 157addName ("downstream" ); 158// Generic downstream linker 159addName ("linker" ); 160 } 161} 162 163 164Index DownstreamArgs ::addName (const String & name ) 165{ 166Index index = findName (name ); 167if (index < 0 ) 168 { 169index = m_entries .getCount (); 170m_entries .add (Entry {name ,CommandLineArgs (m_context )}); 171 } 172return index ; 173} 174 175Index DownstreamArgs ::_findOrAddName ( 176SourceLoc loc , 177const UnownedStringSlice & name , 178Flags flags , 179DiagnosticSink * sink ) 180{ 181if (name .getLength () <=0 ) 182 { 183if (sink ) 184 { 185sink -> diagnose (loc ,MiscDiagnostics ::downstreamToolNameNotDefined ); 186 } 187return -1 ; 188 } 189 190if (flags & Flag ::AllowNewNames ) 191 { 192return addName (name ); 193 } 194 195Index index = findName (name ); 196if (index >=0 ) 197 { 198return index ; 199 } 200 201if (sink ) 202 { 203StringBuilder names ; 204 205names <<"[ " ; 206for (Index i = 0 ;i < m_entries .getCount ();++ i ) 207 { 208if (i ) 209 { 210names <<", " ; 211 } 212names <<m_entries [i ].name ; 213 } 214names <<" ]" ; 215 216sink -> diagnose (loc ,MiscDiagnostics ::downstreamNameNotKnown ,names ); 217 } 218return -1 ; 219} 220 221CommandLineArgs & DownstreamArgs ::getArgsByName (const char * name ) 222{ 223const Index index = findName (name ); 224SLANG_ASSERT (index >=0 ); 225return m_entries [index ].args ; 226} 227 228const CommandLineArgs & DownstreamArgs ::getArgsByName (const char * name )const 229{ 230const Index index = findName (name ); 231SLANG_ASSERT (index >=0 ); 232return m_entries [index ].args ; 233} 234 235SlangResult DownstreamArgs ::stripDownstreamArgs ( 236CommandLineArgs & ioArgs , 237Flags flags , 238DiagnosticSink * sink ) 239{ 240CommandLineReader reader (& ioArgs ,sink ); 241 242while (reader .hasArg ()) 243 { 244const CommandLineArg & arg = reader .peekArg (); 245 246if (arg .value .startsWith ("-X" )) 247 { 248if (arg .value .endsWith ("..." )) 249 { 250const UnownedStringSlice name = 251arg .value .getUnownedSlice ().subString (2 ,arg .value .getLength ()- 5 ); 252const Index nameIndex = _findOrAddName (arg .loc ,name ,flags ,sink ); 253if (nameIndex < 0 ) 254 { 255return SLANG_FAIL ; 256 } 257 258Index depth = 1 ; 259const Index startIndex = reader .getIndex (); 260 261Int index = startIndex + 1 ; 262const Int count = ioArgs .m_args .getCount (); 263 264for (;index < count ;++ index ) 265 { 266const auto & curArg = ioArgs .m_args [index ]; 267 268if (curArg .value == "-X." ) 269 { 270depth -- ; 271// If we are at end of scope we are done 272if (depth <=0 ) 273 { 274break ; 275 } 276 } 277else if (curArg .value .startsWith ("-X" )&& curArg .value .endsWith ("..." )) 278 { 279depth ++ ; 280 } 281 } 282 283// We don't care if its 1, as we allow the main scope to be left open 284if (depth > 1 ) 285 { 286sink -> diagnose (arg .loc ,MiscDiagnostics ::unbalancedDownstreamArguments ); 287return SLANG_FAIL ; 288 } 289 290// We are either at end of scope or at end of list 291SLANG_ASSERT (depth <=0 || index >=count ); 292 293// Add all of these args 294CommandLineArgs & args = getArgsAt (nameIndex ); 295 296// Copy the values in the range 297args .m_args .addRange ( 298ioArgs .m_args .getBuffer ()+ startIndex + 1 , 299index - (startIndex + 1 )); 300 301// If we aren't at the end, we must be pointing to -X., so skip that 302index += Index (index < count ); 303// Remove the range. The readers position, needs to be fixed though 304ioArgs .m_args .removeRange (startIndex ,index - startIndex ); 305 306// The reader should be at startIndex, and so doesn't need fixing 307SLANG_ASSERT (reader .getIndex ()== startIndex ); 308 } 309else if (arg .value == "-X." ) 310 { 311sink -> diagnose (arg .loc ,MiscDiagnostics ::closeOfUnopenDownstreamArgs ); 312return SLANG_FAIL ; 313 } 314else 315 { 316const Index startIndex = reader .getIndex (); 317 318// Extract the name 319UnownedStringSlice name = arg .value .getUnownedSlice ().tail (2 ); 320const Index nameIndex = _findOrAddName (arg .loc ,name ,flags ,sink ); 321if (nameIndex < 0 ) 322 { 323return SLANG_FAIL ; 324 } 325 326reader .advance (); 327 328CommandLineArg nextArg ; 329SLANG_RETURN_ON_FAIL (reader .expectArg (nextArg )); 330 331getArgsAt (nameIndex ).add (nextArg ); 332 333// Rewind to the start index 334reader .setIndex (startIndex ); 335// Remove the args 336ioArgs .m_args .removeRange (startIndex ,2 ); 337 } 338 } 339else 340 { 341// Advance and leave 342reader .advance (); 343 } 344 } 345 346return SLANG_OK ; 347} 348 349}// namespace Slang