X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fgeneral-scheme.cc;h=59893503f5b2a24e01b1553754be8097306e04b1;hb=c9f2e5f23fd435ab69b4313a2e5902556cc91511;hp=76cd33ad7867d160c05e8944460d6327a3c5be9e;hpb=88ee66d5dd83870dad27267781b3d84386264beb;p=lilypond.git diff --git a/lily/general-scheme.cc b/lily/general-scheme.cc index 76cd33ad78..59893503f5 100644 --- a/lily/general-scheme.cc +++ b/lily/general-scheme.cc @@ -1,7 +1,7 @@ /* This file is part of LilyPond, the GNU music typesetter. - Copyright (C) 1998--2010 Jan Nieuwenhuizen + Copyright (C) 1998--2011 Jan Nieuwenhuizen Han-Wen Nienhuys LilyPond is free software: you can redistribute it and/or modify @@ -23,6 +23,7 @@ #include #include #include /* memset */ +#include using namespace std; #include "dimensions.hh" @@ -79,7 +80,9 @@ LY_DEFINE (ly_find_file, "ly:find-file", */ LY_DEFINE (ly_gulp_file, "ly:gulp-file", 1, 1, 0, (SCM name, SCM size), - "Read the file @var{name}, and return its contents in a string." + "Read @var{size} characters from the file @var{name}," + " and return its contents in a string." + " If @var{size} is undefined, the entire file is read." " The file is looked up using the search path.") { LY_ASSERT_TYPE (scm_is_string, name, 1); @@ -144,10 +147,21 @@ LY_DEFINE (ly_programming_error, "ly:programming-error", return SCM_UNSPECIFIED; } +LY_DEFINE (ly_success, "ly:success", + 1, 0, 1, (SCM str, SCM rest), + "A Scheme callable function to issue a success message @var{str}." + " The message is formatted with @code{format} and @var{rest}.") +{ + LY_ASSERT_TYPE (scm_is_string, str, 1); + str = scm_simple_format (SCM_BOOL_F, str, rest); + successful (ly_scm2string (str)); + return SCM_UNSPECIFIED; + +} LY_DEFINE (ly_warning, "ly:warning", 1, 0, 1, (SCM str, SCM rest), - "A Scheme callable function to issue the warning @code{str}." - " The message is formatted with @code{format} and @code{rest}.") + "A Scheme callable function to issue the warning @var{str}." + " The message is formatted with @code{format} and @var{rest}.") { LY_ASSERT_TYPE (scm_is_string, str, 1); str = scm_simple_format (SCM_BOOL_F, str, rest); @@ -233,6 +247,7 @@ is_not_escape_character (Byte c) case '.': case '/': case '0'...'9': + case ':': case 'A'...'Z': case '_': case 'a'...'z': @@ -277,7 +292,7 @@ LY_DEFINE (ly_string_percent_encode, "ly:string-percent-encode", LY_DEFINE (ly_number_2_string, "ly:number->string", 1, 0, 0, (SCM s), - "Convert @var{num} to a string without generating many decimals.") + "Convert @var{s} to a string without generating many decimals.") { LY_ASSERT_TYPE (scm_is_number, s, 1); @@ -439,12 +454,13 @@ LY_DEFINE (ly_stderr_redirect, "ly:stderr-redirect", LY_ASSERT_TYPE (scm_is_string, file_name, 1); string m = "w"; + FILE *stderrfile; if (mode != SCM_UNDEFINED && scm_string_p (mode)) m = ly_scm2string (mode); /* dup2 and (fileno (current-error-port)) do not work with mingw'c gcc -mwindows. */ fflush (stderr); - freopen (ly_scm2string (file_name).c_str (), m.c_str (), stderr); + stderrfile = freopen (ly_scm2string (file_name).c_str (), m.c_str (), stderr); return SCM_UNSPECIFIED; } @@ -461,7 +477,7 @@ LY_DEFINE (ly_hash_table_keys, "ly:hash-table-keys", 1,0,0, (SCM tab), "Return a list of keys in @var{tab}.") { - return scm_internal_hash_fold ((Hash_closure_function) & accumulate_symbol, + return scm_internal_hash_fold ((scm_t_hash_fold_fn) &accumulate_symbol, NULL, SCM_EOL, tab); } @@ -551,7 +567,7 @@ format_single_argument (SCM arg, int precision, bool escape = false) return (ly_symbol2string (arg)); else { - ly_progress (scm_from_locale_string ("Unsupported SCM value for format: ~a"), + ly_progress (scm_from_locale_string ("\nUnsupported SCM value for format: ~a"), scm_list_1 (arg)); } @@ -561,8 +577,8 @@ format_single_argument (SCM arg, int precision, bool escape = false) LY_DEFINE (ly_format, "ly:format", 1, 0, 1, (SCM str, SCM rest), - "LilyPond specific format, supporting @code{~a} and @code{~[0-9]f}. " - "Basic support for @code{~s} is also provided.") + "LilyPond specific format, supporting @code{~a} and @code{~[0-9]f}." + " Basic support for @code{~s} is also provided.") { LY_ASSERT_TYPE (scm_is_string, str, 1); @@ -631,7 +647,7 @@ LY_DEFINE (ly_format, "ly:format", if (scm_is_pair (rest)) programming_error (string (__FUNCTION__) - + ": too many arguments"); + + ": too many arguments"); vsize len = 0; for (vsize i = 0; i < results.size (); i++) @@ -648,3 +664,64 @@ LY_DEFINE (ly_format, "ly:format", return scm_take_locale_stringn (result, len); } + +int +ly_run_command (char *argv[], char **standard_output, char **standard_error) +{ + GError *error = 0; + int exit_status = 0; + int flags = G_SPAWN_SEARCH_PATH; + if (!standard_output) + flags |= G_SPAWN_STDOUT_TO_DEV_NULL; + if (!standard_error) + flags |= G_SPAWN_STDERR_TO_DEV_NULL; + if (!g_spawn_sync (0, argv, 0, GSpawnFlags (flags), + 0, 0, + standard_output, standard_error, + &exit_status, &error)) + { + fprintf (stderr, "failed (%d): %s: %s\n", exit_status, argv[0], error->message); + g_error_free (error); + if (!exit_status) + exit_status = -1; + } + + return exit_status; +} + +LY_DEFINE (ly_spawn, "ly:spawn", + 1, 0, 1, (SCM command, SCM rest), + "Simple interface to g_spawn_sync" + " @var{str}." + " The error is formatted with @code{format} and @var{rest}.") + +{ + LY_ASSERT_TYPE (scm_is_string, command, 1); + + int argc = scm_is_pair (rest) ? scm_ilength (rest) : 0; + char **argv = new char*[argc + 2]; + + int n = 0; + argv[n++] = ly_scm2str0 (command); + for (SCM s = rest; scm_is_pair (s); s = scm_cdr (s)) + argv[n++] = ly_scm2str0 (scm_car (s)); + argv[n] = 0; + + char *standard_output = 0; + char *standard_error = 0; + int exit_status = be_verbose_global + ? ly_run_command (argv, &standard_output, &standard_error) + : ly_run_command (argv, 0, 0); + + if (be_verbose_global) + { + fprintf (stderr, "\n%s", standard_output); + fprintf (stderr, "%s", standard_error); + } + + for (int i = 0; i < n; i++) + free (argv[i]); + delete[] argv; + + return scm_from_int (exit_status); +}