summaryrefslogtreecommitdiff
path: root/Build/source/texk/gregorio/gregorio-4.0.0-beta2/src/gregorio-utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/gregorio/gregorio-4.0.0-beta2/src/gregorio-utils.c')
-rw-r--r--Build/source/texk/gregorio/gregorio-4.0.0-beta2/src/gregorio-utils.c638
1 files changed, 638 insertions, 0 deletions
diff --git a/Build/source/texk/gregorio/gregorio-4.0.0-beta2/src/gregorio-utils.c b/Build/source/texk/gregorio/gregorio-4.0.0-beta2/src/gregorio-utils.c
new file mode 100644
index 00000000000..c2a4b8b579d
--- /dev/null
+++ b/Build/source/texk/gregorio/gregorio-4.0.0-beta2/src/gregorio-utils.c
@@ -0,0 +1,638 @@
+/*
+ * Copyright (C) 2006-2015 The Gregorio Project (see CONTRIBUTORS.md)
+ *
+ * This file is part of Gregorio.
+ *
+ * Gregorio is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Gregorio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Gregorio. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#ifdef USE_KPSE
+#include <kpathsea/kpathsea.h>
+#define gregorio_basename xbasename
+#else
+#include <getopt.h>
+#include <libgen.h> /* for basename */
+#define gregorio_basename basename
+#endif
+#include <string.h> /* for strcmp */
+#include <locale.h>
+#include <limits.h>
+#include "struct.h"
+#include "plugins.h"
+#include "messages.h"
+#include "characters.h"
+#include "support.h"
+#include "gabc/gabc.h"
+#include "vowel/vowel.h"
+
+#ifndef MODULE_PATH_ENV
+#define MODULE_PATH_ENV "MODULE_PATH"
+#endif
+
+typedef enum gregorio_file_format {
+ FORMAT_UNSET = 0,
+ GABC,
+ GTEX,
+ DUMP
+} gregorio_file_format;
+
+#define GABC_STR "gabc"
+#define GTEX_STR "gtex"
+#define DUMP_STR "dump"
+
+#define DEFAULT_INPUT_FORMAT GABC
+#define DEFAULT_OUTPUT_FORMAT GTEX
+
+/* realpath is not in mingw32 */
+#ifdef _WIN32
+#ifndef PATH_MAX
+#define PATH_MAX _MAX_PATH
+#endif
+#define realpath(path,resolved_path) _fullpath(resolved_path, path, PATH_MAX)
+#endif
+
+static char *define_path(char *current_directory, char *string)
+{
+ int length;
+ char *file_name;
+ char temp_name[PATH_MAX];
+ char *base_name;
+#ifdef _WIN32
+ char *last_backslash;
+#endif
+
+ file_name = malloc(PATH_MAX * sizeof(char));
+
+ strcpy(temp_name, string);
+ base_name = strrchr(temp_name, '/');
+#ifdef _WIN32
+ last_backslash = strrchr(temp_name, '\\');
+ if (last_backslash > base_name) {
+ base_name = last_backslash;
+ }
+#endif
+ if (base_name) {
+ /* some path was supplied */
+
+ *base_name = '\0';
+ base_name++;
+
+ /* try to resolve it */
+ if (!realpath(temp_name, file_name)) {
+ fprintf(stderr, "the directory %s for %s does not exist\n",
+ file_name, base_name);
+ exit(-1);
+ }
+ } else {
+ /* no path was supplied */
+ base_name = string;
+ strcpy(file_name, current_directory);
+ }
+
+ /* make sure we're not bigger than PATH_MAX */
+ length = strlen(file_name);
+ if (length + strlen(base_name) + 1 >= PATH_MAX) {
+ fprintf(stderr, "filename too long: %s/%s\n", file_name, base_name);
+ exit(-1);
+ }
+ /* build the file name */
+ file_name[length] = '/';
+ strcpy(file_name + length + 1, base_name);
+
+ return file_name;
+}
+
+/* function that returns the filename without the extension */
+static char *get_base_filename(char *fbasename)
+{
+ char *p;
+ int l;
+ char *ret;
+ p = strrchr(fbasename, '.');
+ if (!p) {
+ return NULL;
+ }
+ l = strlen(fbasename) - strlen(p);
+ ret = (char *) malloc((l + 1) * sizeof(char));
+ gregorio_snprintf(ret, l + 1, "%s", fbasename);
+ ret[l] = '\0';
+ return ret;
+}
+
+/* function that adds the good extension to a basename (without extension) */
+static char *get_output_filename(char *fbasename, const char *extension)
+{
+ char *output_filename = NULL;
+ output_filename =
+ (char *) malloc(sizeof(char) *
+ (strlen(extension) + strlen(fbasename) + 2));
+ output_filename = strcpy(output_filename, fbasename);
+ output_filename = strcat(output_filename, ".");
+ output_filename = strcat(output_filename, extension);
+ return output_filename;
+}
+
+/*
+ * the type definitions of the function to read a score from a file, and to
+ * write a score to a file. Necessary for the libtool stuff...
+ */
+
+static void print_licence(void)
+{
+ printf("\n\
+Tools for manipulation of gregorian chant files\n\
+Copyright (C) 2006-2015 Gregorio project authors (see CONTRIBUTORS.md)\n\
+\n\
+This program is free software: you can redistribute it and/or modify\n\
+it under the terms of the GNU General Public License as published by\n\
+the Free Software Foundation, either version 3 of the License, or\n\
+(at your option) any later version.\n\
+\n");
+ printf("This program is distributed in the hope that it will be useful,\n\
+but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\
+GNU General Public License for more details.\n\
+\n\
+You should have received a copy of the GNU General Public License\n\
+along with this program. If not, see <http://www.gnu.org/licenses/>.\n\n");
+}
+
+static void print_usage(char *name)
+{
+ printf(_("\nUsage :\n%s [OPTION] {file}\n where OPTION is :\n\
+\t-o file writes output to specified file\n\
+\t-S writes output to stdout\n\
+\t-F format specifies output file format (default: gtex)\n\
+\t-l file writes messages output to specified file (default: stderr)\n\
+\t-f format specifies input file format (default: gabc)\n\
+\t-s reads input from stdin\n\
+\t-p generate point-and-click information\n\
+\t-h displays this message\n\
+\t-V displays %s version\n"), name, name);
+ printf(_("\t-L displays licence\n\
+\t-v verbose mode\n\
+\t-W displays all warnings\n\
+\n\
+available formats are:\n\
+\t gabc gabc\n\
+\t gtex GregorioTeX\n\
+\t dump simple text dump (for debugging purpose)\n\
+\n"));
+}
+
+static void check_input_clobber(char *input_file_name, char *output_file_name)
+{
+ char *absolute_input_file_name;
+ char *absolute_output_file_name;
+ char *current_directory;
+ int file_cmp;
+ if (input_file_name && output_file_name) {
+ current_directory = malloc(PATH_MAX * sizeof(char));
+ current_directory = getcwd(current_directory, PATH_MAX);
+ if (current_directory == NULL) {
+ fprintf(stderr, _("can't determine current directory"));
+ free(current_directory);
+ exit(-1);
+ }
+ absolute_input_file_name = define_path(current_directory, input_file_name);
+ absolute_output_file_name = define_path(current_directory, output_file_name);
+ file_cmp = strcmp(absolute_input_file_name, absolute_output_file_name);
+ if (file_cmp == 0) {
+ fprintf(stderr, "error: refusing to overwrite the input file\n");
+ }
+ free(current_directory);
+ free(absolute_input_file_name);
+ free(absolute_output_file_name);
+ if (file_cmp == 0) {
+ exit(-1);
+ }
+ }
+}
+
+static char *encode_point_and_click_filename(char *input_file_name)
+{
+ /* percent-encoding favors capital hex digits */
+ static const char *const hex = "0123456789ABCDEF";
+ char filename[PATH_MAX], *result = NULL, *r = NULL, *p;
+
+ if (!realpath(input_file_name, filename)) {
+ fprintf(stderr, "error: unable to resolve %s\n", input_file_name);
+ exit(-1);
+ }
+
+ /* 2 extra characters for a possible leading slash and final NUL */
+ r = result = malloc((strlen(filename) * 4 + 2) * sizeof(char));
+
+#ifdef _WIN32
+ *(r++) = '/';
+#endif
+
+ for (p = filename; *p; ++p) {
+#ifdef _WIN32
+ if (*p == '\\') {
+ *p = '/';
+ }
+#endif
+
+ /* note that -, _ and ~ are conspicuously missing from this list
+ * because they cause trouble in TeX; we will percent-encode them */
+ if ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p < 'z')
+ || (*p >= '0' && *p <= '9') || *p == '.' || *p == '/'
+#ifdef _WIN32
+ || *p == ':'
+#endif
+ ) {
+ *(r++) = *p;
+ }
+ else {
+ /* percent-encode anything else */
+ *(r++) = '\\'; /* must escape it because it's TeX */
+ *(r++) = '%';
+ *(r++) = hex[(*p >> 4) & 0x0FU];
+ *(r++) = hex[*p & 0x0FU];
+ }
+ }
+
+ *r = '\0';
+
+ return result;
+}
+
+int main(int argc, char **argv)
+{
+ const char *copyright =
+ "Copyright (C) 2006-2015 Gregorio project authors (see CONTRIBUTORS.md)";
+ int c;
+
+ char *input_file_name = NULL;
+ char *output_file_name = NULL;
+ char *output_basename = NULL;
+ char *error_file_name = NULL;
+ FILE *input_file = NULL;
+ FILE *output_file = NULL;
+ FILE *error_file = NULL;
+ gregorio_file_format input_format = FORMAT_UNSET;
+ gregorio_file_format output_format = FORMAT_UNSET;
+ gregorio_verbosity verb_mode = 0;
+ bool point_and_click = false;
+ char *point_and_click_filename = NULL;
+ int number_of_options = 0;
+ int option_index = 0;
+ static struct option long_options[] = {
+ {"output-file", 1, 0, 'o'},
+ {"stdout", 0, 0, 'S'},
+ {"output-format", 1, 0, 'F'},
+ {"messages-file", 1, 0, 'l'},
+ {"input-format", 1, 0, 'f'},
+ {"stdin", 0, 0, 's'},
+ {"help", 0, 0, 'h'},
+ {"version", 0, 0, 'V'},
+ {"licence", 0, 0, 'L'},
+ {"verbose", 0, 0, 'v'},
+ {"all-warnings", 0, 0, 'W'},
+ {"point-and-click", 0, 0, 'p'},
+ };
+ gregorio_score *score = NULL;
+
+ #ifdef USE_KPSE
+ kpse_set_program_name("gregorio", "gregorio");
+ #endif
+ if (argc == 1) {
+ print_usage(argv[0]);
+ exit(0);
+ }
+ setlocale(LC_CTYPE, "C");
+
+ while (1) {
+ c = getopt_long(argc, argv, "o:SF:l:f:shOLVvWp",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+ switch (c) {
+ case 'o':
+ if (output_file_name) {
+ fprintf(stderr,
+ "warning: several output files declared, %s taken\n",
+ output_file_name);
+ break;
+ }
+ if (output_file) { /* means that stdout is defined */
+ fprintf(stderr,
+ "warning: can't write to file and stdout, writing on stdout\n");
+ break;
+ }
+ output_file_name = optarg;
+ break;
+ case 'S':
+ if (output_file_name) {
+ fprintf(stderr,
+ "warning: can't write to file and stdout, writing on %s\n",
+ output_file_name);
+ break;
+ }
+ if (output_file) { /* means that stdout is defined */
+ fprintf(stderr, "warning: option used two times: %c\n", c);
+ break;
+ }
+ output_file = stdout;
+ break;
+ case 'F':
+ if (output_format) {
+ fprintf(stderr,
+ "warning: several output formats declared, first taken\n");
+ break;
+ }
+ if (!strcmp(optarg, GABC_STR)) {
+ output_format = GABC;
+ break;
+ }
+ if (!strcmp(optarg, GTEX_STR)) {
+ output_format = GTEX;
+ break;
+ }
+ if (!strcmp(optarg, DUMP_STR)) {
+ output_format = DUMP;
+ break;
+ } else {
+ fprintf(stderr, "error: unknown output format: %s\n", optarg);
+ exit(0);
+ }
+ break;
+ case 'l':
+ if (error_file_name) {
+ fprintf(stderr,
+ "warning: several error files declared, %s taken\n",
+ error_file_name);
+ break;
+ }
+ error_file_name = optarg;
+ break;
+ case 'f':
+ if (input_format) {
+ gregorio_set_error_out(error_file);
+ fprintf(stderr,
+ "warning: several output formats declared, first taken\n");
+ break;
+ }
+ if (!strcmp(optarg, GABC_STR)) {
+ input_format = GABC;
+ break;
+ } else {
+ fprintf(stderr, "error: unknown input format: %s\n", optarg);
+ exit(0);
+ }
+ break;
+ case 's':
+ if (input_file_name) {
+ fprintf(stderr,
+ "warning: can't read from file and stdin, writing on %s\n",
+ input_file_name);
+ break;
+ }
+ if (input_file) { /* means that stdin is defined */
+ fprintf(stderr, "warning: option used two times: %c\n", c);
+ break;
+ }
+ input_file = stdin;
+ break;
+ case 'h':
+ print_usage(argv[0]);
+ exit(0);
+ break;
+ case 'V':
+ printf("Gregorio version %s.\n%s\n", GREGORIO_VERSION, copyright);
+ exit(0);
+ break;
+ case 'v':
+ if (verb_mode && verb_mode != VERBOSITY_WARNING) {
+ fprintf(stderr, "warning: verbose option passed two times\n");
+ break;
+ }
+ verb_mode = VERBOSITY_INFO;
+ break;
+ case 'W':
+ if (verb_mode == VERBOSITY_WARNING) {
+ fprintf(stderr,
+ "warning: all-warnings option passed two times\n");
+ break;
+ }
+ if (verb_mode != VERBOSITY_INFO) {
+ verb_mode = VERBOSITY_WARNING;
+ }
+ break;
+ case 'L':
+ print_licence();
+ exit(0);
+ break;
+ case 'p':
+ if (point_and_click) {
+ fprintf(stderr,
+ "warning: point-and-click option passed two times\n");
+ break;
+ }
+ point_and_click = true;
+ break;
+ case '?':
+ break;
+ default:
+ fprintf(stderr, "unknown option: %c\n", c);
+ print_usage(argv[0]);
+ exit(0);
+ break;
+ }
+ number_of_options++;
+ } /* end of while */
+ if (optind == argc) {
+ if (!input_file) { /* input not undefined (could be stdin) */
+ fprintf(stderr, "error: no input file specified\n");
+ print_usage(argv[0]);
+ exit(-1);
+ }
+ } else {
+ input_file_name = argv[optind];
+ output_basename = get_base_filename(input_file_name);
+ if (input_file) {
+ fprintf(stderr,
+ "warning: can't read from stdin and a file, reading from file %s\n",
+ input_file_name);
+ input_file = NULL;
+ }
+ }
+ optind++;
+ if (optind < argc) {
+ printf("ignored arguments: ");
+ while (number_of_options < argc)
+ printf("%s ", argv[number_of_options++]);
+ printf("\n");
+ }
+
+ if (!input_format) {
+ input_format = DEFAULT_INPUT_FORMAT;
+ }
+
+ if (!output_format) {
+ output_format = DEFAULT_OUTPUT_FORMAT;
+ }
+
+ #ifdef USE_KPSE
+ if (!kpse_in_name_ok(input_file_name)) {
+ fprintf(stderr, "Error: kpse doesn't allow to read from file %s\n",
+ input_file_name);
+ exit(-1);
+ }
+ #endif
+
+ /* then we act... */
+
+ if (!output_file_name && !output_file) {
+ if (!output_basename) {
+ output_file = stdout;
+ } else {
+ if (input_format != output_format) {
+ switch (output_format) {
+ case GABC:
+ output_file_name =
+ get_output_filename(output_basename, "gabc");
+ break;
+ case GTEX:
+ output_file_name =
+ get_output_filename(output_basename, "gtex");
+ break;
+ case DUMP:
+ output_file_name =
+ get_output_filename(output_basename, "dump");
+ break;
+ default:
+ fprintf(stderr, "error: unsupported format");
+ exit(-1);
+ }
+ }
+ }
+ }
+ if (output_basename) {
+ free(output_basename);
+ }
+
+ if (!output_file) {
+ if (!input_file) {
+ check_input_clobber(input_file_name, output_file_name);
+ }
+ #ifdef USE_KPSE
+ if (!kpse_out_name_ok(output_file_name)) {
+ fprintf(stderr, "Error: kpse doesn't allow to write in file %s\n",
+ output_file_name);
+ exit(-1);
+ }
+ #endif
+ output_file = fopen(output_file_name, "wb");
+ if (!output_file) {
+ fprintf(stderr, "error: can't write in file %s",
+ output_file_name);
+ }
+ }
+
+ /* we always have input_file or input_file_name */
+ if (input_file) {
+ if (point_and_click) {
+ fprintf(stderr,
+ "warning: disabling point-and-click since reading from stdin\n");
+ point_and_click = false;
+ }
+ } else {
+ input_file = fopen(input_file_name, "r");
+ if (!input_file) {
+ fprintf(stderr, "error: can't open file %s for reading\n",
+ input_file_name);
+ exit(-1);
+ }
+ gregorio_set_file_name(gregorio_basename(input_file_name));
+ if (point_and_click) {
+ point_and_click_filename = encode_point_and_click_filename(
+ input_file_name);
+ }
+ }
+
+ if (!error_file_name) {
+ error_file = stderr;
+ gregorio_set_error_out(error_file);
+ } else {
+ error_file = fopen(error_file_name, "wb");
+ if (!error_file) {
+ fprintf(stderr, "error: can't open file %s for writing\n",
+ error_file_name);
+ exit(-1);
+ }
+ gregorio_set_error_out(error_file);
+ }
+
+ if (!verb_mode) {
+ verb_mode = VERBOSITY_DEPRECATION;
+ }
+
+ gregorio_set_verbosity_mode(verb_mode);
+
+ switch (input_format) {
+ case GABC:
+ score = gabc_read_score(input_file);
+ break;
+ default:
+ fprintf(stderr, "error : invalid input format\n");
+ fclose(input_file);
+ fclose(output_file);
+ exit(-1);
+ break;
+ }
+
+ fclose(input_file);
+ if (score == NULL) {
+ fclose(output_file);
+ fprintf(stderr, "error in file parsing\n");
+ exit(-1);
+ }
+
+ gregorio_fix_initial_keys(score, DEFAULT_KEY);
+
+ switch (output_format) {
+ case GABC:
+ gabc_write_score(output_file, score);
+ break;
+ case GTEX:
+ gregoriotex_write_score(output_file, score, point_and_click_filename);
+ break;
+ case DUMP:
+ dump_write_score(output_file, score);
+ break;
+ default:
+ fprintf(stderr, "error : invalid output format\n");
+ gregorio_free_score(score);
+ fclose(output_file);
+ exit(-1);
+ break;
+ }
+ fclose(output_file);
+ if (point_and_click_filename) {
+ free(point_and_click_filename);
+ }
+ gregorio_free_score(score);
+ gregorio_vowel_tables_free();
+ gabc_score_determination_lex_destroy();
+ gabc_notes_determination_lex_destroy();
+ gregorio_vowel_rulefile_lex_destroy();
+
+ exit(gregorio_get_return_value());
+}