@@ -279,6 +279,8 @@ static int run_repl(int verbose) {
279279
280280int main (int argc , char * * argv ) {
281281 const char * path = NULL ;
282+ int source_mode = 0 ;
283+ char * source_text = NULL ;
282284 int verbose_flag = 0 ;
283285 int explicit_ext_count = 0 ;
284286
@@ -304,6 +306,24 @@ int main(int argc, char** argv) {
304306 continue ;
305307 }
306308
309+ if (strcmp (arg , "-source" ) == 0 ) {
310+ if (i + 1 >= argc ) {
311+ fprintf (stderr , "Missing argument for -source\n" );
312+ extensions_shutdown ();
313+ builtins_reset_dynamic ();
314+ return PREFIX_ERROR_IO ;
315+ }
316+ source_mode = 1 ;
317+ source_text = strdup (argv [++ i ]);
318+ if (!source_text ) {
319+ extensions_shutdown ();
320+ builtins_reset_dynamic ();
321+ fprintf (stderr , "Out of memory\n" );
322+ return PREFIX_ERROR_MEMORY ;
323+ }
324+ continue ;
325+ }
326+
307327 if (is_extension_arg (arg )) {
308328 char * err = NULL ;
309329 if (load_extension_input (arg , & err ) != 0 ) {
@@ -342,7 +362,7 @@ int main(int argc, char** argv) {
342362 }
343363 free (err );
344364
345- if (path ) {
365+ if (path && ! source_mode ) {
346366 char * prog_dir = path_dirname_dup (path );
347367 char * base = path_basename_no_ext_dup (path );
348368 if (!prog_dir || !base ) {
@@ -414,7 +434,7 @@ int main(int argc, char** argv) {
414434 }
415435 }
416436
417- if (!path ) {
437+ if (!path && ! source_mode ) {
418438 int repl_rc = run_repl (verbose_flag );
419439 extensions_shutdown ();
420440 builtins_reset_dynamic ();
@@ -423,17 +443,30 @@ int main(int argc, char** argv) {
423443
424444 char * src = NULL ;
425445 char * source_label = NULL ;
426- /* Canonicalize the provided program path now so it's correct even if
427- the process changes cwd below. This prevents relative paths like
428- "./tests/test2.pre" from resolving incorrectly after chdir. */
446+
447+ if (source_mode ) {
448+ source_label = strdup ("<source>" );
449+ src = strdup (source_text ? source_text : "" );
450+ if (!source_label || !src ) {
451+ free (source_label );
452+ free (src );
453+ extensions_shutdown ();
454+ builtins_reset_dynamic ();
455+ fprintf (stderr , "Out of memory\n" );
456+ return PREFIX_ERROR_MEMORY ;
457+ }
458+ } else {
459+ /* Canonicalize the provided program path now so it's correct even if
460+ the process changes cwd below. This prevents relative paths like
461+ "./tests/test2.pre" from resolving incorrectly after chdir. */
429462#if defined(_MSC_VER )
430- if (path ) source_label = _fullpath (NULL , path , 0 );
463+ if (path ) source_label = _fullpath (NULL , path , 0 );
431464#else
432- if (path ) source_label = realpath (path , NULL );
465+ if (path ) source_label = realpath (path , NULL );
433466#endif
434- if (!source_label && path ) source_label = strdup (path );
467+ if (!source_label && path ) source_label = strdup (path );
435468
436- FILE * f = fopen (path , "rb" );
469+ FILE * f = fopen (path , "rb" );
437470 if (!f ) {
438471 fprintf (stderr , "Failed to open '%s'\n" , path );
439472 extensions_shutdown ();
@@ -462,6 +495,7 @@ int main(int argc, char** argv) {
462495 size_t r = fread (src , 1 , (size_t )sz , f );
463496 src [r ] = '\0' ;
464497 fclose (f );
498+ }
465499
466500 Lexer lex ;
467501 lexer_init (& lex , src , source_label );
@@ -472,6 +506,7 @@ int main(int argc, char** argv) {
472506 Stmt * program = parser_parse (& parser );
473507 if (parser .had_error ) {
474508 free (src );
509+ if (source_text ) free (source_text );
475510 extensions_shutdown ();
476511 builtins_reset_dynamic ();
477512 return PREFIX_ERROR_SYNTAX ;
@@ -503,13 +538,15 @@ int main(int argc, char** argv) {
503538 if (res .error ) free (res .error );
504539 free (src );
505540 if (source_label ) free (source_label );
541+ if (source_text ) free (source_text );
506542 extensions_shutdown ();
507543 builtins_reset_dynamic ();
508544 return PREFIX_ERROR_RUNTIME ;
509545 }
510546
511547 free (src );
512548 if (source_label ) free (source_label );
549+ if (source_text ) free (source_text );
513550 extensions_shutdown ();
514551 builtins_reset_dynamic ();
515552 return PREFIX_SUCCESS ;
0 commit comments