diff -Nru abcm2ps-7.8.9/abc2ps.c abcm2ps-8.14.2/abc2ps.c
--- abcm2ps-7.8.9/abc2ps.c 2014-03-26 08:08:20.000000000 +0000
+++ abcm2ps-8.14.2/abc2ps.c 1970-01-01 00:00:00.000000000 +0000
@@ -1,980 +0,0 @@
-/*
- * abcm2ps: a program to typeset tunes written in ABC format using PostScript
- *
- * Copyright (C) 1998-2014 Jean-François Moine (http://moinejf.free.fr)
- *
- * Adapted from abc2ps-1.2.5:
- * Copyright (C) 1996,1997 Michael Methfessel (msm@ihp-ffo.de)
- *
- * This program 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 2 of the License, or
- * (at your option) any later version.
- *
- * This program 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 this program; if not, see .
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#ifdef linux
-#include
-#endif
-
-#include "abc2ps.h"
-#include "front.h"
-
-/* -- global variables -- */
-
-INFO info;
-unsigned char deco[256];
-struct SYMBOL *sym; /* (points to the symbols of the current voice) */
-
-int tunenum; /* number of current tune */
-int pagenum = 1; /* current page in output file */
-
- /* switches modified by command line flags: */
-int quiet; /* quiet mode */
-int secure; /* secure mode */
-int annotate; /* output source references */
-int pagenumbers; /* write page numbers */
-int epsf; /* for EPSF (1) or SVG (2) output */
-int svg; /* SVG (1) or XML (2 - HTML + SVG) output */
-int showerror; /* show the errors */
-
-char outfn[FILENAME_MAX]; /* output file name */
-int file_initialized; /* for output file */
-FILE *fout; /* output file */
-char *in_fname; /* current input file name */
-time_t mtime; /* last modification time of the input file */
-static time_t fmtime; /* " " of all files */
-
-int s_argc; /* command line arguments */
-char **s_argv;
-
-struct tblt_s *tblts[MAXTBLT];
-struct cmdtblt_s cmdtblts[MAXCMDTBLT];
-int ncmdtblt;
-
-/* -- local variables -- */
-
-static char abc_fn[FILENAME_MAX]; /* buffer for ABC file name */
-static char *styd = DEFAULT_FDIR; /* format search directory */
-static int def_fmt_done = 0; /* default format read */
-static struct SYMBOL notitle;
-
-/* memory arena (for clrarena, lvlarena & getarena) */
-#define MAXAREAL 3 /* max area levels:
- * 0; global, 1: tune, 2: generation */
-#define AREANASZ 8192 /* standard allocation size */
-#define MAXAREANASZ 0x20000 /* biggest allocation size */
-static int str_level; /* current arena level */
-static struct str_a {
- struct str_a *n; /* next area */
- char *p; /* pointer in area */
- int r; /* remaining space in area */
- int sz; /* size of str[] */
- char str[2]; /* start of memory area */
-} *str_r[MAXAREAL], *str_c[MAXAREAL]; /* root and current area pointers */
-
-/* -- local functions -- */
-static void read_def_format(void);
-static void treat_file(char *fn, char *ext);
-
-static FILE *open_ext(char *fn, char *ext)
-{
- FILE *fp;
- char *p;
-
- if ((fp = fopen(fn, "rb")) != NULL)
- return fp;
- if ((p = strrchr(fn, DIRSEP)) == NULL)
- p = fn;
- if (strrchr(p, '.') != NULL)
- return NULL;
- strcat(p, ".");
- strcat(p, ext);
- if ((fp = fopen(fn, "rb")) != NULL)
- return fp;
- return NULL;
-}
-
-/* -- open a file for reading -- */
-FILE *open_file(char *fn, /* file name */
- char *ext, /* file type */
- char *rfn) /* returned real file name */
-{
- FILE *fp;
- char *p;
- int l;
-
- /* if there was some ABC file, try its directory */
- if (in_fname && in_fname != fn
- && (p = strrchr(in_fname, DIRSEP)) != NULL) {
- l = p - in_fname + 1;
- strncpy(rfn, in_fname, l);
- strcpy(&rfn[l], fn);
- if ((fp = open_ext(rfn, ext)) != NULL)
- return fp;
- }
-
- /* try locally */
- strcpy(rfn, fn);
- if ((fp = open_ext(rfn, ext)) != NULL)
- return fp;
-
- /* try a format in the format directory */
- if (*ext != 'f' || *styd == '\0')
- return NULL;
- l = strlen(styd) - 1;
- if (styd[l] == DIRSEP)
- sprintf(rfn, "%s%s", styd, fn);
- else
- sprintf(rfn, "%s%c%s", styd, DIRSEP, fn);
- return open_ext(rfn, ext);
-}
-
-/* -- read a whole input file -- */
-/* the real/full file name is put in tex_buf[] */
-static char *read_file(char *fn, char *ext)
-{
- size_t fsize;
- FILE *fin;
- char *file;
-
- if (*fn == '\0') {
- strcpy(tex_buf, "stdin");
- fsize = 0;
- file = malloc(8192);
- for (;;) {
- int l;
-
- l = fread(&file[fsize], 1, 8192, stdin);
- fsize += l;
- if (l != 8192)
- break;
- file = realloc(file, fsize + 8192);
- }
- if (ferror(stdin) != 0) {
- free(file);
- return 0;
- }
- if (fsize % 8192 == 0)
- file = realloc(file, fsize + 2);
- time(&fmtime);
- } else {
- struct stat sbuf;
-
- fin = open_file(fn, ext, tex_buf);
- if (!fin)
- return NULL;
- if (fseek(fin, 0L, SEEK_END) < 0) {
- fclose(fin);
- return NULL;
- }
- fsize = ftell(fin);
- rewind(fin);
- if ((file = malloc(fsize + 2)) == NULL) {
- fclose(fin);
- return NULL;
- }
-
- if (fread(file, 1, fsize, fin) != fsize) {
- fclose(fin);
- free(file);
- return NULL;
- }
- fstat(fileno(fin), &sbuf);
- memcpy(&fmtime, &sbuf.st_mtime, sizeof fmtime);
- fclose(fin);
- }
- file[fsize] = '\0';
- return file;
-}
-
-/* call back to handle %%format/%%abc-include - see front.c */
-static void include_cb(unsigned char *fn)
-{
- char abc_fn_sav[FILENAME_MAX];
-
- strcpy(abc_fn_sav, abc_fn);
- treat_file((char *) fn, "fmt");
- strcpy(abc_fn, abc_fn_sav);
-}
-
-/* -- treat an input file and generate the ABC file -- */
-static void treat_file(char *fn, char *ext)
-{
- struct abctune *t;
- char *file, *file2;
- int file_type, l;
- static int nbfiles;
-
- if (nbfiles > 2) {
- error(1, 0, "Too many included files");
- return;
- }
-
- /* initialize if not already done */
- if (!fout)
- read_def_format();
-
- /* read the file into memory */
- /* the real/full file name is in tex_buf[] */
- if ((file = read_file(fn, ext)) == NULL) {
- if (strcmp(fn, "default.fmt") != 0) {
- error(1, NULL, "Cannot read the input file '%s'", fn);
-#if defined(unix) || defined(__unix__)
- perror(" read_file");
-#endif
- }
- return;
- }
- if (!quiet)
- fprintf(stderr, "File %s\n", tex_buf);
-
- /* convert the strings */
- l = strlen(tex_buf);
- if (strcmp(&tex_buf[l - 3], ".ps") == 0) {
- file_type = FE_PS;
- frontend((unsigned char *) "%%beginps\n", 0);
- } else if (strcmp(&tex_buf[l - 4], ".fmt") == 0) {
- file_type = FE_FMT;
- } else {
- file_type = FE_ABC;
- strcpy(abc_fn, tex_buf);
- in_fname = abc_fn;
- mtime = fmtime;
- }
-
- nbfiles++;
- file2 = (char *) frontend((unsigned char *) file, file_type);
- nbfiles--;
- free(file);
-
- if (file_type == FE_PS) /* PostScript file */
- file2 = (char *) frontend((unsigned char *) "%%endps", 0);
-
- if (nbfiles > 0) /* if %%format */
- return; /* don't free the preprocessed buffer */
-
-// memcpy(&deco_tune, &deco_glob, sizeof deco_tune);
- if (file_type == FE_ABC) { /* if ABC file */
-// if (!epsf)
-// open_output_file();
- clrarena(1); /* clear previous tunes */
- }
- t = abc_parse(file2);
- free(file2);
- front_init(0, 0, include_cb); /* reinit the front-end */
- if (!t) {
- if (file_type == FE_ABC)
- error(1, NULL, "File '%s' is empty!", tex_buf);
- return;
- }
-
- while (t) {
- if (t->first_sym) /*fixme:last tune*/
- do_tune(t); /* generate */
- t = t->next;
- }
-/* abc_free(t); (useless) */
-}
-
-/* -- read the default format -- */
-static void read_def_format(void)
-{
- if (def_fmt_done)
- return;
- def_fmt_done = 1;
- treat_file("default.fmt", "fmt");
-}
-
-/* -- set extension on a file name -- */
-void strext(char *fn, char *ext)
-{
- char *p, *q;
-
- if ((p = strrchr(fn, DIRSEP)) == NULL)
- p = fn;
- if ((q = strrchr(p, '.')) == NULL)
- strcat(p, ".");
- else
- q[1] = '\0';
- strcat(p, ext);
-}
-
-/* -- write the program version -- */
-static void display_version(int full)
-{
- fputs("abcm2ps-" VERSION " (" VDATE ")\n", stderr);
- if (!full)
- return;
- fputs("Compiled: " __DATE__ "\n"
- "Options:"
-#ifdef A4_FORMAT
- " A4_FORMAT"
-#endif
-#ifdef DECO_IS_ROLL
- " DECO_IS_ROLL"
-#endif
-#ifdef HAVE_PANGO
- " PANGO"
-#endif
-#if !defined(A4_FORMAT) && !defined(DECO_IS_ROLL) && !defined(HAVE_PANGO)
- " NONE"
-#endif
- "\n", stderr);
- if (styd[0] != '\0')
- fprintf(stderr, "Default format directory: %s\n", styd);
-}
-
-/* -- display usage and exit -- */
-static void usage(void)
-{
- display_version(0);
- printf( "ABC to Postscript translator.\n"
- "Usage: abcm2ps [options] file [file_options] ..\n"
- "where:\n"
- " file input ABC file, or '-'\n"
- " options and file_options:\n"
- " .output file options:\n"
- " -E produce EPSF output, one tune per file\n"
- " -g produce SVG output, one tune per file\n"
- " -v produce SVG output, one page per file\n"
- " -X produce SVG output in one XHTML file\n"
- " -O fff set outfile name to fff\n"
- " -O = make outfile name from infile/title\n"
- " -i indicate where are the errors\n"
- " -k kk size of the PS output buffer in Kibytes\n"
- " .output formatting:\n"
- " -s xx set scale factor to xx\n"
- " -w xx set staff width (cm/in/pt)\n"
- " -m xx set left margin (cm/in/pt)\n"
- " -d xx set staff separation (cm/in/pt)\n"
- " -a xx set max shrinkage to xx (between 0 and 1)\n"
- " -F foo read format file \"foo.fmt\"\n"
- " -D bar look for format files in directory \"bar\"\n"
- " .output options:\n"
- " -l landscape mode\n"
- " -I xx indent 1st line (cm/in/pt)\n"
- " -x add xref numbers in titles\n"
- " -M don't output the lyrics\n"
- " -N n set page numbering mode to n=\n"
- " 0=off 1=left 2=right 3=even left,odd right 4=even right,odd left\n"
- " -1 write one tune per page\n"
- " -G no slur in grace notes\n"
- " -j n[b] number the measures every n bars (or on the left if n=0)\n"
- " if 'b', display in a box\n"
- " -b n set the first measure number to n\n"
- " -f have flat beams\n"
- " -T n[v] output the tablature 'n' for voice 'v' / all voices\n"
- " .line breaks:\n"
- " -c auto line break\n"
- " -B n break every n bars\n"
- " .input file selection/options:\n"
- " -e pattern\n"
- " tune selection\n"
- " .help/configuration:\n"
- " -V show program version\n"
- " -h show this command summary\n"
- " -H show the format parameters\n"
- " -S secure mode\n"
- " -q quiet mode\n");
- exit(EXIT_SUCCESS);
-}
-
-#ifdef linux
-/* -- where is the default format directory -- */
-static void wherefmtdir(void)
-{
- char exe[512], *p;
- FILE *f;
- int l;
-
- if ((l = readlink("/proc/self/exe", exe, sizeof exe)) <= 0)
- return;
- if ((p = strrchr(exe, '/')) == NULL)
- return;
- p++;
- if (p > &exe[5] && strncmp(p - 5, "/bin", 4) == 0) {
- strcpy(p - 4, "share/abcm2ps/");
- p += -4 + 14;
- }
- /* else, assume this is the source directory */
-
- /* check if a format file is present */
- strcpy(p, "tight.fmt");
- if ((f = fopen(exe, "r")) == NULL)
- return;
- fclose(f);
-
- /* change the format directory */
- p[-1] = '\0';
- styd = strdup(exe);
-}
-#endif
-
-/* -- parse the tablature command ('-T n[v]') -- */
-static struct cmdtblt_s *cmdtblt_parse(char *p)
-{
- struct cmdtblt_s *cmdtblt;
- short val;
-
- if (ncmdtblt >= MAXCMDTBLT) {
- error(1, NULL, "++++ Too many '-T'");
- return NULL;
- }
- if (*p == '\0')
- val = -1;
- else {
- val = *p++ - '0' - 1;
- if ((unsigned) val > MAXTBLT) {
- error(1, NULL, "++++ Bad tablature number in '-T'\n");
- return 0;
- }
- }
- cmdtblt = &cmdtblts[ncmdtblt++];
- cmdtblt->index = val;
- cmdtblt->vn = p;
- return cmdtblt;
-}
-
-/* set a command line option */
-static void set_opt(char *w, char *v)
-{
- static char prefix = '%'; /* pseudo-comment prefix */
-
- if (!v)
- v = "";
- if (strlen(w) + strlen(v) >= TEX_BUF_SZ - 10) {
- error(1, NULL, "Command line '%s' option too long", w);
- return;
- }
- sprintf(tex_buf, /* this buffer is available */
- "%%%c%s %s lock\n", prefix, w, v);
- if (strcmp(w, "abcm2ps") == 0)
- prefix = *v;
- frontend((unsigned char *) tex_buf, 0);
-}
-
-/* -- main program -- */
-int main(int argc, char **argv)
-{
- unsigned j;
- char *p, c, *aaa;
-
- if (argc <= 1)
- usage();
-
- /* set the global flags */
- s_argc = argc;
- s_argv = argv;
- aaa = NULL;
- while (--argc > 0) {
- argv++;
- p = *argv;
- if (*p != '-' || p[1] == '-') {
- if (*p == '+' && p[1] == 'F') /* +F : no default format */
- def_fmt_done = 1;
- continue;
- }
- while ((c = *++p) != '\0') { /* '-xxx' */
- switch (c) {
- case 'E':
- svg = 0; /* EPS */
- epsf = 1;
- break;
- case 'g':
- svg = 0; /* SVG one file per tune */
- epsf = 2;
- break;
- case 'h':
- usage(); /* no return */
- case 'q':
- quiet = 1;
- break;
- case 'S':
- secure = 1;
- break;
- case 'V':
- display_version(1);
- return EXIT_SUCCESS;
- case 'v':
- svg = 1; /* SVG one file per pagee */
- epsf = 0;
- break;
- case 'X':
- svg = 2; /* SVG/XHTML */
- epsf = 0;
- break;
- case 'k':
- if (p[1] == '\0') {
- if (--argc <= 0) {
- error(1, NULL, "No value for '-k' - aborting");
- return EXIT_FAILURE;
- }
- aaa = *++argv;
- } else {
- aaa = p + 1;
- p += strlen(p) - 1;
- }
- break;
- default:
- if (strchr("aBbDdeFfIjmNOsTw", c)) /* if with arg */
- p += strlen(p) - 1; /* skip */
- break;
- }
- }
- }
- if (!quiet)
- display_version(0);
-
- /* initialize */
- outfn[0] = '\0';
- clrarena(0); /* global */
- clrarena(1); /* tunes */
- clrarena(2); /* generation */
- if (aaa) { /* '-k' output buffer size */
- int kbsz;
-
- sscanf(aaa, "%d", &kbsz);
- init_outbuf(kbsz);
- } else {
- init_outbuf(0);
- }
- abc_init(getarena, /* alloc */
- 0, /* free */
- (void (*)(int level)) lvlarena, /* new level */
- sizeof(struct SYMBOL) - sizeof(struct abcsym),
- 0); /* don't keep comments */
-// memset(&info, 0, sizeof info);
- info['T' - 'A'] = ¬itle;
- notitle.as.text = "T:";
- set_format();
- reset_deco();
- front_init(0, 0, include_cb);
-
-#ifdef linux
- /* if not set, try to find where is the default format directory */
- if (styd[0] == '\0')
- wherefmtdir();
-#endif
-#ifdef HAVE_PANGO
- pg_init();
-#endif
-
- /* parse the arguments - finding a new file, treat the previous one */
- argc = s_argc;
- argv = s_argv;
- while (--argc > 0) {
- argv++;
- p = *argv;
- if ((c = *p) == '\0')
- continue;
- if (c == '-') {
- int i;
-
- if (p[1] == '\0') { /* '-' alone */
- if (in_fname) {
- treat_file(in_fname, "abc");
- frontend((unsigned char *) "select\n", 0);
- }
- in_fname = ""; /* read from stdin */
- continue;
- }
- i = strlen(p) - 1;
- if (p[i] == '-'
- && p[1] != '-'
-//fixme: 'e' may be preceded by other options
- && p[1] != 'e'
- && p[i -1] != 'O')
- c = '+'; /* switch off flags with '-x-' */
- }
- if (c == '+') { /* switch off flags with '+' */
- while (*++p != '\0') {
- switch (*p) {
- case '-':
- break;
- case 'B':
- cfmt.barsperstaff = 0;
- lock_fmt(&cfmt.barsperstaff);
- break;
- case 'c':
- cfmt.continueall = 0;
- lock_fmt(&cfmt.continueall);
- break;
- case 'F':
-// def_fmt_done = 1;
- break;
- case 'G':
- cfmt.graceslurs = 1;
- lock_fmt(&cfmt.graceslurs);
- break;
- case 'i':
- showerror = 0;
- break;
- case 'j':
- cfmt.measurenb = -1;
- lock_fmt(&cfmt.measurenb);
- break;
- case 'l':
- cfmt.landscape = 0;
- lock_fmt(&cfmt.landscape);
- break;
- case 'M':
- cfmt.fields[1] = 1 << ('w' - 'a');
- lock_fmt(&cfmt.fields);
- break;
- case 'N':
- pagenumbers = 0;
- break;
- case 'O':
- outfn[0] = '\0';
- break;
- case 'T': {
- struct cmdtblt_s *cmdtblt;
-
- aaa = p + 1;
- if (*aaa == '\0') {
- if (argc > 1
- && argv[1][0] != '-') {
- aaa = *++argv;
- argc--;
- }
- } else {
- while (p[1] != '\0') /* stop */
- p++;
- if (*p == '-')
- *p-- = '\0'; /* (not clean) */
- }
- cmdtblt = cmdtblt_parse(aaa);
- if (cmdtblt != 0)
- cmdtblt->active = 0;
- break;
- }
- case 'x':
- cfmt.fields[0] &= ~(1 << ('X' - 'A'));
- lock_fmt(&cfmt.fields);
- break;
- case '0':
- cfmt.splittune = 0;
- lock_fmt(&cfmt.splittune);
- break;
- case '1':
- cfmt.oneperpage = 0;
- lock_fmt(&cfmt.oneperpage);
- break;
- default:
- error(1, NULL,
- "++++ Cannot switch off flag: +%c",
- *p);
- break;
- }
- }
- continue;
- }
-
- if (c == '-') { /* interpret a flag with '-' */
- if (p[1] == '-') { /* long argument */
- p += 2;
- if (--argc <= 0) {
- error(1, NULL, "No argument for '--'");
- return EXIT_FAILURE;
- }
- argv++;
- set_opt(p, *argv);
- continue;
- }
- while ((c = *++p) != '\0') {
- switch (c) {
-
- /* simple flags */
- case 'A':
- annotate = 1;
- break;
- case 'c':
- cfmt.continueall = 1;
- lock_fmt(&cfmt.continueall);
- break;
- case 'E':
- break;
- case 'f':
- cfmt.flatbeams = 1;
- lock_fmt(&cfmt.flatbeams);
- break;
- case 'G':
- cfmt.graceslurs = 0;
- lock_fmt(&cfmt.graceslurs);
- break;
- case 'g':
- break;
- case 'H':
- if (!fout) {
- read_def_format();
- make_font_list();
- }
- print_format();
- return EXIT_SUCCESS;
- case 'i':
- showerror = 1;
- break;
- case 'l':
- cfmt.landscape = 1;
- lock_fmt(&cfmt.landscape);
- break;
- case 'M':
- cfmt.fields[1] &= ~(1 << ('w' - 'a'));
- lock_fmt(&cfmt.fields);
- break;
- case 'q':
- case 'S':
- break;
- case 'v':
- case 'X':
- break;
- case 'x':
- cfmt.fields[0] |= 1 << ('X' - 'A');
- lock_fmt(&cfmt.fields);
- break;
- case '0':
- cfmt.splittune = 1;
- lock_fmt(&cfmt.splittune);
- break;
- case '1':
- cfmt.oneperpage = 1;
- lock_fmt(&cfmt.oneperpage);
- break;
-
- /* flag with optional parameter */
- case 'N':
- if (p[1] == '\0'
- && (argc <= 1
- || !isdigit((unsigned) argv[1][0]))) {
- pagenumbers = 2; /* old behaviour */
- break;
- }
- /* fall thru */
- /* flags with parameter.. */
- case 'a':
- case 'B':
- case 'b':
- case 'D':
- case 'd':
- case 'e':
- case 'F':
- case 'I':
- case 'j':
- case 'k':
- case 'L':
- case 'm':
- case 'O':
- case 's':
- case 'T':
- case 'w':
- aaa = p + 1;
- if (*aaa == '\0') {
- aaa = *++argv;
- if (--argc <= 0
- || (*aaa == '-' && c != 'O')) {
- error(1, NULL,
- "Missing parameter after '-%c' - aborting",
- c);
- return EXIT_FAILURE;
- }
- } else {
- p += strlen(p) - 1; /* stop */
- }
-
- if (strchr("BbfjkNs", c)) { /* check num args */
- for (j = 0; j < strlen(aaa); j++) {
- if (!strchr("0123456789.",
- aaa[j])) {
- if (aaa[j] == 'b'
- && aaa[j + 1] == '\0'
- && c == 'j')
- break;
- error(1, NULL,
- "Invalid parameter <%s> for flag -%c",
- aaa, c);
- return EXIT_FAILURE;
- }
- }
- }
-
- switch (c) {
- case 'a':
- set_opt("maxshrink", aaa);
- break;
- case 'B':
- set_opt("barsperstaff", aaa);
- break;
- case 'b':
- set_opt("measurefirst", aaa);
- break;
- case 'D':
- styd = aaa;
- break;
- case 'd':
- set_opt("staffsep", aaa);
- break;
- case 'e':
- set_opt("select", aaa);
- break;
- case 'F':
- treat_file(aaa, "fmt");
- break;
- case 'I':
- set_opt("indent", aaa);
- break;
- case 'j':
- sscanf(aaa, "%d", &cfmt.measurenb);
- lock_fmt(&cfmt.measurenb);
- if (aaa[strlen(aaa) - 1] == 'b')
- cfmt.measurebox = 1;
- else
- cfmt.measurebox = 0;
- lock_fmt(&cfmt.measurebox);
- break;
- case 'k':
- break;
- case 'm':
- set_opt("leftmargin", aaa);
- break;
- case 'N':
- sscanf(aaa, "%d", &pagenumbers);
- if ((unsigned) pagenumbers > 4) {
- error(1, NULL,
- "'-N' value %s - changed to 2",
- aaa);
- pagenumbers = 2;
- }
- break;
- case 'O':
- if (strlen(aaa) >= sizeof outfn) {
- error(1, NULL, "'-O' too large - aborting");
- exit(EXIT_FAILURE);
- }
- strcpy(outfn, aaa);
- break;
- case 's':
- set_opt("scale", aaa);
- break;
- case 'T': {
- struct cmdtblt_s *cmdtblt;
-
- cmdtblt = cmdtblt_parse(aaa);
- if (cmdtblt)
- cmdtblt->active = 1;
- break;
- }
- case 'w':
- set_opt("staffwidth", aaa);
- break;
- }
- break;
- default:
- error(1, NULL,
- "Unknown flag: -%c ignored", c);
- break;
- }
- }
- continue;
- }
-
- if (in_fname) {
- treat_file(in_fname, "abc");
- frontend((unsigned char *) "select\n", 0);
- }
- in_fname = p;
- }
-
- if (in_fname)
- treat_file(in_fname, "abc");
- if (multicol_start != 0) { /* lack of %%multicol end */
- error(1, NULL, "Lack of %%%%multicol end");
- multicol_start = 0;
- buffer_eob();
- if (!info['X' - 'A']
- && !epsf)
- write_buffer();
- }
- if (!epsf && !fout) {
- error(1, NULL, "No input file specified");
- return EXIT_FAILURE;
- }
- close_output_file();
- return severity == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
-}
-
-/* -- arena routines -- */
-void clrarena(int level)
-{
- struct str_a *a_p;
-
- if ((a_p = str_r[level]) == NULL) {
- str_r[level] = a_p = malloc(sizeof *str_r[0] + AREANASZ - 2);
- a_p->sz = AREANASZ;
- a_p->n = 0;
- }
- str_c[level] = a_p;
- a_p->p = a_p->str;
- a_p->r = sizeof a_p->str;
-}
-
-int lvlarena(int level)
-{
- int old_level;
-
- old_level = str_level;
- str_level = level;
- return old_level;
-}
-
-/* The area is 8 bytes aligned to handle correctly int and pointers access
- * on some machines as Sun Sparc. */
-void *getarena(int len)
-{
- char *p;
- struct str_a *a_p;
-
- a_p = str_c[str_level];
- len = (len + 7) & ~7; /* align at 64 bits boundary */
- if (len > a_p->r) {
- if (len > MAXAREANASZ) {
- error(1, NULL,
- "getarena - data too wide %d - aborting",
- len);
- exit(EXIT_FAILURE);
- }
- if (len > AREANASZ) { /* big allocation */
- struct str_a *a_n;
-
- a_n = a_p->n;
- a_p->n = malloc(sizeof *str_r[0] + len - 2);
- a_p->n->n = a_n;
- a_p->n->sz = len;
- } else if (a_p->n == 0) { /* standard allocation */
- a_p->n = malloc(sizeof *str_r[0] + AREANASZ - 2);
- a_p->n->n = 0;
- a_p->n->sz = AREANASZ;
- }
- str_c[str_level] = a_p = a_p->n;
- a_p->p = a_p->str;
- a_p->r = a_p->sz;
- }
- p = a_p->p;
- a_p->p += len;
- a_p->r -= len;
- return p;
-}
diff -Nru abcm2ps-7.8.9/abc2ps.h abcm2ps-8.14.2/abc2ps.h
--- abcm2ps-7.8.9/abc2ps.h 2014-04-01 18:23:39.000000000 +0000
+++ abcm2ps-8.14.2/abc2ps.h 1970-01-01 00:00:00.000000000 +0000
@@ -1,614 +0,0 @@
-/* -- general macros -- */
-
-#include
-#include
-
-#include "config.h"
-#include "abcparse.h"
-
-#define OUTPUTFILE "Out.ps" /* standard output file */
-#ifndef WIN32
-#define DIRSEP '/'
-#else
-#define DIRSEP '\\'
-#endif
-
-#define CM * 28.35 /* factor to transform cm to pt */
-#define PT /* factor to transform pt to pt */
-#define IN * 72.0 /* factor to transform inch to pt */
-
-/* basic page dimensions */
-#ifdef A4_FORMAT
-#define PAGEHEIGHT (29.7 CM)
-#define PAGEWIDTH (21.0 CM)
-#define MARGIN (1.8 CM)
-#else
-#define PAGEHEIGHT (11.0 IN)
-#define PAGEWIDTH (8.5 IN)
-#define MARGIN (0.7 IN)
-#endif
-
-/* -- macros controlling music typesetting -- */
-
-#define STEM_YOFF 1.0 /* offset stem from note center */
-#define STEM_XOFF 3.5
-#define STEM 20 /* default stem height */
-#define STEM_MIN 16 /* min stem height under beams */
-#define STEM_MIN2 14 /* ... for notes with two beams */
-#define STEM_MIN3 12 /* ... for notes with three beams */
-#define STEM_MIN4 10 /* ... for notes with four beams */
-#define STEM_CH_MIN 14 /* min stem height for chords under beams */
-#define STEM_CH_MIN2 10 /* ... for notes with two beams */
-#define STEM_CH_MIN3 9 /* ... for notes with three beams */
-#define STEM_CH_MIN4 9 /* ... for notes with four beams */
-#define BEAM_DEPTH 3.2 /* width of a beam stroke */
-#define BEAM_OFFSET 0.25 /* pos of flat beam relative to staff line */
-#define BEAM_SHIFT 5.0 /* shift of second and third beams */
-/* To align the 4th beam as the 1st: shift=6-(depth-2*offset)/3 */
-#define BEAM_FLATFAC 0.6 /* factor to decrease slope of long beams */
-#define BEAM_THRESH 0.06 /* flat beam if slope below this threshold */
-#define BEAM_SLOPE 0.5 /* max slope of a beam */
-#define BEAM_STUB 6.0 /* length of stub for flag under beam */
-#define SLUR_SLOPE 1.0 /* max slope of a slur */
-#define DOTSHIFT 5 /* dot shift when up flag on note */
-#define GSTEM 14 /* grace note stem length */
-#define GSTEM_XOFF 1.6 /* x offset for grace note stem */
-
-#define BETA_C 0.1 /* max expansion for flag -c */
-#define BETA_X 1.0 /* max expansion before complaining */
-
-#define VOCPRE 0.4 /* portion of vocals word before note */
-#define GCHPRE 0.4 /* portion of guitar chord before note */
-
-/* -- Parameters for note spacing -- */
-/* fnn multiplies the spacing under a beam, to compress the notes a bit */
-
-#define fnnp 0.9
-
-/* -- macros for program internals -- */
-
-#define STRL1 256 /* string length for file names */
-#define MAXSTAFF 16 /* max staves */
-#define BSIZE 512 /* buffer size for one input string */
-
-#define BREVE (BASE_LEN * 2) /* double note (square note) */
-#define SEMIBREVE BASE_LEN /* whole note */
-#define MINIM (BASE_LEN / 2) /* half note (white note) */
-#define CROTCHET (BASE_LEN / 4) /* quarter note (black note) */
-#define QUAVER (BASE_LEN / 8) /* 1/8 note */
-#define SEMIQUAVER (BASE_LEN / 16) /* 1/16 note */
-
-#define MAXFONTS 30 /* max number of fonts */
-
-#define T_LEFT 0
-#define T_JUSTIFY 1
-#define T_FILL 2
-#define T_CENTER 3
-#define T_SKIP 4
-#define T_RIGHT 5
-
-#define YSTEP 128 /* number of steps for y offsets */
-
-extern unsigned char deco[256];
-
-struct FONTSPEC {
- int fnum; /* index to font tables in format.c */
- float size;
- float swfac;
-};
-extern char *fontnames[MAXFONTS]; /* list of font names */
-
-/* lyrics */
-#define LY_HYPH 0x10 /* replacement character for hyphen */
-#define LY_UNDER 0x11 /* replacement character for underscore */
-#define MAXLY 16 /* max number of lyrics */
-struct lyl {
- struct FONTSPEC *f; /* font */
- float w; /* width */
- float s; /* shift / note */
- char t[1]; /* word */
-};
-struct lyrics {
- struct lyl *lyl[MAXLY]; /* ptr to lyric lines */
-};
-
-/* guitar chord / annotations */
-#define MAXGCH 8 /* max number of guitar chords / annotations */
-struct gch {
- char type; /* ann. char, 'g' gchord, 'r' repeat, '\0' end */
- unsigned char idx; /* index in as.text */
- unsigned char font; /* font */
- char box; /* 1 if in box */
- float x, y; /* x y offset / note + (top or bottom) of staff */
- float w; /* width */
-};
-
-/* positions / directions */
-/* 0: auto, 1: above/up (SL_ABOVE), 2: below/down (SL_BELOW)
- * 3: hidden (SL_AUTO) or opposite for gstemdir */
-#define SL_HIDDEN SL_AUTO
-struct posit_s {
- unsigned short dyn:2; /* %%dynamic */
- unsigned short gch:2; /* %%gchord */
- unsigned short orn:2; /* %%ornament */
- unsigned short voc:2; /* %%vocal */
- unsigned short vol:2; /* %%volume */
- unsigned short std:2; /* %%stemdir */
- unsigned short gsd:2; /* %%gstemdir */
-};
-
-/* music element */
-struct SYMBOL { /* struct for a drawable symbol */
- struct abcsym as; /* abc symbol !!must be the first field!! */
- struct SYMBOL *next, *prev; /* voice linkage */
- struct SYMBOL *ts_next, *ts_prev; /* time linkage */
- struct SYMBOL *extra; /* extra symbols (grace notes, tempo... */
- unsigned char type; /* symbol type */
-#define NO_TYPE 0 /* invalid type */
-#define NOTEREST 1 /* valid symbol types */
-#define SPACE 2
-#define BAR 3
-#define CLEF 4
-#define TIMESIG 5
-#define KEYSIG 6
-#define TEMPO 7
-#define STAVES 8
-#define MREST 9
-#define PART 10
-#define GRACE 11
-#define FMTCHG 12
-#define TUPLET 13
-#define STBRK 14
-#define CUSTOS 15
-#define NSYMTYPES 16
- unsigned char voice; /* voice (0..nvoice) */
- unsigned char staff; /* staff (0..nstaff) */
- unsigned char nhd; /* number of notes in chord - 1 */
- int dur; /* main note duration */
- signed char pits[MAXHD]; /* pitches for notes */
- int time; /* starting time */
- unsigned int sflags; /* symbol flags */
-#define S_EOLN 0x0001 /* end of line */
-#define S_BEAM_ST 0x0002 /* beam starts here */
-#define S_BEAM_BR1 0x0004 /* 2nd beam must restart here */
-#define S_BEAM_BR2 0x0008 /* 3rd beam must restart here */
-#define S_BEAM_END 0x0010 /* beam ends here */
-#define S_OTHER_HEAD 0x0020 /* don't draw any note head */
-#define S_IN_TUPLET 0x0040 /* in a tuplet */
-#define S_TREM2 0x0080 /* tremolo on 2 notes */
-#define S_RRBAR 0x0100 /* right repeat bar (when bar) */
-#define S_XSTEM 0x0200 /* cross-staff stem (when note) */
-#define S_BEAM_ON 0x0400 /* continue beaming */
-#define S_SL1 0x0800 /* some chord slur start */
-#define S_SL2 0x1000 /* some chord slur end */
-#define S_TI1 0x2000 /* some chord tie start */
-#define S_PERC 0x4000 /* percussion */
-#define S_RBSTOP 0x8000 /* repeat bracket stop */
-#define S_FEATHERED_BEAM 0x00010000 /* feathered beam */
-#define S_REPEAT 0x00020000 /* sequence / measure repeat */
-#define S_NL 0x00040000 /* start of new music line */
-#define S_SEQST 0x00080000 /* start of vertical sequence */
-#define S_SECOND 0x00100000 /* symbol on a secondary voice */
-#define S_FLOATING 0x00200000 /* symbol on a floating voice */
-#define S_NOREPBRA 0x00400000 /* don't print the repeat bracket */
-#define S_TREM1 0x00800000 /* tremolo on 1 note */
-#define S_TEMP 0x01000000 /* temporary symbol */
-#define S_SHIFTUNISON_1 0x02000000 /* %%shiftunison 1 */
-#define S_SHIFTUNISON_2 0x04000000 /* %%shiftunison 2 */
- struct posit_s posit; /* positions / directions */
- signed char stem; /* 1 / -1 for stem up / down */
- signed char nflags; /* number of note flags when > 0 */
- char dots; /* number of dots */
- unsigned char head; /* head type */
-#define H_FULL 0
-#define H_EMPTY 1
-#define H_OVAL 2
-#define H_SQUARE 3
- signed char multi; /* multi voice in the staff (+1, 0, -1) */
- signed char nohdix; /* no head index (for unison) */
- short u; /* auxillary information:
- * - CLEF: small clef
- * - KEYSIG: old key signature
- * - BAR: new bar number
- * - TUPLET: tuplet format
- * - NOTE: tremolo number / feathered beam
- * - FMTCHG (format change): subtype */
-#define PSSEQ 0 /* postscript sequence */
-#define SVGSEQ 1 /* SVG sequence */
-#define REPEAT 2 /* repeat sequence or measure
- * doty: # measures if > 0
- * # notes/rests if < 0
- * nohdix: # repeat */
- float x; /* x offset */
- signed char y; /* y offset of note head */
- signed char ymn, ymx, yav; /* min, max, avg note head y offset */
- float xmx; /* max h-pos of a head rel to top
- * width when STBRK */
- float xs, ys; /* coord of stem end / bar height */
- float wl, wr; /* left, right min width */
- float space; /* natural space before symbol */
- float shrink; /* minimum space before symbol */
- float xmax; /* max x offset */
- float shhd[MAXHD]; /* horizontal shift for heads */
- float shac[MAXHD]; /* horizontal shift for accidentals */
- struct gch *gch; /* guitar chords / annotations */
- struct lyrics *ly; /* lyrics */
- signed char doty; /* NOTEREST: y pos of dot when voices overlap
- * STBRK: forced
- * FMTCHG REPEAT: infos */
-};
-
-/* bar types !tied to abcparse.h! */
-#define B_SINGLE B_BAR /* | single bar */
-#define B_DOUBLE 0x11 /* || thin double bar */
-#define B_THIN_THICK 0x13 /* |] thick at section end */
-#define B_THICK_THIN 0x21 /* [| thick at section start */
-#define B_LREP 0x14 /* |: left repeat bar */
-#define B_RREP 0x41 /* :| right repeat bar */
-#define B_DREP 0x44 /* :: double repeat bar */
-#define B_DASH 0x04 /* : dashed bar */
-
-extern unsigned short *micro_tb; /* ptr to the microtone table of the tune */
-
-struct FORMAT { /* struct for page layout */
- float pageheight, pagewidth;
- float topmargin, botmargin, leftmargin, rightmargin;
- float topspace, wordsspace, titlespace, subtitlespace, partsspace;
- float composerspace, musicspace, vocalspace, textspace;
- float breaklimit, maxshrink, lineskipfac, parskipfac, stemheight;
- float indent, infospace, slurheight, notespacingfactor, scale;
- float staffsep, sysstaffsep, maxstaffsep, maxsysstaffsep, stretchlast;
- int abc2pscompat, alignbars, aligncomposer, autoclef;
- int barsperstaff, breakoneoln, bstemdown, cancelkey;
- int combinevoices, contbarnb, continueall, custos;
- int dblrepbar, dynalign, flatbeams;
- int infoline, gchordbox, graceslurs, gracespace, hyphencont;
- int keywarn, landscape, linewarn;
- int measurebox, measurefirst, measurenb, micronewps, microscale;
- int oneperpage;
-#ifdef HAVE_PANGO
- int pango;
-#endif
- int partsbox, pdfmark;
- int setdefl, shiftunison, splittune, squarebreve;
- int staffnonote, straightflags, stretchstaff;
- int textoption, titlecaps, titleleft, titletrim;
- int timewarn, transpose, tuplets;
- char *bgcolor, *dateformat, *header, *footer, *titleformat;
-#define FONT_UMAX 5 /* max number of user fonts */
-#define ANNOTATIONFONT 5
-#define COMPOSERFONT 6
-#define FOOTERFONT 7
-#define GCHORDFONT 8
-#define HEADERFONT 9
-#define HISTORYFONT 10
-#define INFOFONT 11
-#define MEASUREFONT 12
-#define PARTSFONT 13
-#define REPEATFONT 14
-#define SUBTITLEFONT 15
-#define TEMPOFONT 16
-#define TEXTFONT 17
-#define TITLEFONT 18
-#define VOCALFONT 19
-#define VOICEFONT 20
-#define WORDSFONT 21
-#define FONT_DYN 22 /* index of dynamic fonts (gch, an, ly) */
-#define FONT_DYNX 12 /* number of dynamic fonts */
-#define FONT_MAX (FONT_DYN+FONT_DYNX) /* whole number of fonts */
- struct FONTSPEC font_tb[FONT_MAX];
- char ndfont; /* current index of dynamic fonts */
- unsigned char gcf, anf, vof; /* fonts for guitar chords,
- * annotations and lyrics */
- unsigned int fields[2]; /* info fields to print
- *[0] is 'A'..'Z', [1] is 'a'..'z' */
- struct posit_s posit;
-};
-
-extern struct FORMAT cfmt; /* current format */
-extern struct FORMAT dfmt; /* global format */
-
-typedef struct SYMBOL *INFO[26]; /* information fields ('A' .. 'Z') */
-extern INFO info;
-
-extern char *outbuf; /* output buffer.. should hold one tune */
-extern char *mbf; /* where to PUTx() */
-extern int use_buffer; /* 1 if lines are being accumulated */
-
-extern int outft; /* last font in the output file */
-extern int tunenum; /* number of current tune */
-extern int pagenum; /* current page number */
-extern int nbar; /* current measure number */
-extern int in_page;
-extern int defl; /* decoration flags */
-#define DEF_NOST 0x01 /* long deco with no start */
-#define DEF_NOEN 0x02 /* long deco with no end */
-#define DEF_STEMUP 0x04 /* stem up (1) or down (0) */
-
- /* switches modified by flags: */
-extern int quiet; /* quiet mode */
-extern int secure; /* secure mode */
-extern int annotate; /* output source references */
-extern int pagenumbers; /* write page numbers */
-extern int epsf; /* EPSF (1) / SVG (2) output */
-extern int svg; /* SVG (1) or XML (2 - HTML + SVG) output */
-extern int showerror; /* show the errors */
-
-extern char outfn[FILENAME_MAX]; /* output file name */
-extern char *in_fname; /* current input file name */
-extern time_t mtime; /* last modification time of the input file */
-
-extern int file_initialized; /* for output file */
-extern FILE *fout; /* output file */
-
-#define MAXTBLT 8
-struct tblt_s {
- char *head; /* PS head function */
- char *note; /* PS note function */
- char *bar; /* PS bar function */
- float wh; /* width of head */
- float ha; /* height above the staff */
- float hu; /* height under the staff */
- short pitch; /* pitch when no associated 'w:' / 0 */
- char instr[2]; /* instrument pitch */
-};
-extern struct tblt_s *tblts[MAXTBLT];
-
-#define MAXCMDTBLT 4 /* max number of -T in command line */
-struct cmdtblt_s {
- short index; /* tablature number */
- short active; /* activate or not */
- char *vn; /* voice name */
-};
-extern struct cmdtblt_s cmdtblts[MAXCMDTBLT];
-extern int ncmdtblt;
-
-extern int s_argc; /* command line arguments */
-extern char **s_argv;
-
-struct STAFF_S {
- struct clef_s clef; /* base clef */
- char forced_clef; /* explicit clef */
- char empty; /* no symbol on this staff */
- short botbar, topbar; /* bottom and top of bar */
- float y; /* y position */
- float top[YSTEP], bot[YSTEP]; /* top/bottom y offsets */
-};
-extern struct STAFF_S staff_tb[MAXSTAFF];
-extern int nstaff; /* (0..MAXSTAFF-1) */
-
-struct VOICE_S {
- struct VOICE_S *next; /* link */
- struct SYMBOL *sym; /* associated symbols */
- struct SYMBOL *last_sym; /* last symbol while scanning */
- struct SYMBOL *lyric_start; /* start of lyrics while scanning */
- char id[VOICE_ID_SZ]; /* voice id */
- char *nm; /* voice name */
- char *snm; /* voice subname */
- char *bar_text; /* bar text at start of staff when bar_start */
- struct gch *bar_gch; /* bar text */
- struct SYMBOL *tie; /* note with ties of previous line */
- struct SYMBOL *rtie; /* note with ties before 1st repeat bar */
- struct tblt_s *tblts[2]; /* tablatures */
- float scale; /* scale */
- int time; /* current time (parsing) */
- struct clef_s clef; /* current clef */
- struct key_s key; /* current key signature */
- struct meter_s meter; /* current time signature */
- struct key_s ckey; /* key signature while parsing */
- struct key_s okey; /* original key signature (parsing) */
- unsigned hy_st; /* lyrics hyphens at start of line (bit array) */
- unsigned ignore:1; /* ignore this voice (%%staves) */
- unsigned forced_clef:1; /* explicit clef */
- unsigned second:1; /* secondary voice in a brace/parenthesis */
- unsigned floating:1; /* floating voice in a brace system */
- unsigned bar_repeat:1; /* bar at start of staff is a repeat bar */
- unsigned norepbra:1; /* don't display the repeat brackets */
- unsigned have_ly:1; /* some lyrics in this voice */
- unsigned new_name:1; /* redisplay the voice name */
- unsigned space:1; /* have a space before the next note (parsing) */
- unsigned perc:1; /* percussion */
- unsigned auto_len:1; /* auto L: (parsing) */
- short wmeasure; /* measure duration (parsing) */
- short transpose; /* transposition (parsing) */
- short bar_start; /* bar type at start of staff / 0 */
- struct posit_s posit; /* positions / directions */
- signed char octave; /* octave (parsing) */
- signed char clone; /* duplicate from this voice number */
- signed char over; /* overlay of this voice number */
- unsigned char staff; /* staff (0..n-1) */
- unsigned char cstaff; /* staff (parsing) */
- unsigned char slur_st; /* slurs at start of staff */
-};
-extern struct VOICE_S voice_tb[MAXVOICE]; /* voice table */
-extern struct VOICE_S *first_voice; /* first_voice */
-
-extern struct SYMBOL *tsfirst; /* first symbol in the time linked list */
-extern struct SYMBOL *tsnext; /* next line when cut */
-extern float realwidth; /* real staff width while generating */
-
-#define NFLAGS_SZ 10 /* size of note flags tables */
-#define C_XFLAGS 5 /* index of crotchet in flags tables */
-extern float space_tb[NFLAGS_SZ]; /* note spacing */
-
-struct SYSTEM { /* staff system */
- struct SYSTEM *next;
- short top_voice; /* first voice in the staff system */
- short nstaff;
- struct {
- short flags;
-#define OPEN_BRACE 0x01
-#define CLOSE_BRACE 0x02
-#define OPEN_BRACKET 0x04
-#define CLOSE_BRACKET 0x08
-#define OPEN_PARENTH 0x10
-#define CLOSE_PARENTH 0x20
-#define STOP_BAR 0x40
-#define FL_VOICE 0x80
-#define OPEN_BRACE2 0x0100
-#define CLOSE_BRACE2 0x0200
-#define OPEN_BRACKET2 0x0400
-#define CLOSE_BRACKET2 0x0800
- char empty;
- char dum;
- struct clef_s clef;
- float sep, maxsep;
- } staff[MAXSTAFF];
- struct {
- signed char range;
- unsigned char staff;
- char second;
- char dum;
- float sep, maxsep;
- struct clef_s clef;
- } voice[MAXVOICE];
-};
-struct SYSTEM *cursys; /* current staff system */
-
-/* -- external routines -- */
-/* abc2ps.c */
-void clrarena(int level);
-int lvlarena(int level);
-void *getarena(int len);
-void strext(char *fid, char *ext);
-/* buffer.c */
-void a2b(char *fmt, ...)
-#ifdef __GNUC__
- __attribute__ ((format (printf, 1, 2)))
-#endif
- ;
-void block_put(void);
-void buffer_eob(void);
-void marg_init(void);
-void bskip(float h);
-void check_buffer(void);
-void init_outbuf(int kbsz);
-void close_output_file(void);
-void close_page(void);
-float get_bposy(void);
-void write_buffer(void);
-int (*output)(FILE *out, const char *fmt, ...)
-#ifdef __GNUC__
- __attribute__ ((format (printf, 2, 3)))
-#endif
- ;
-void write_eps(void);
-/* deco.c */
-void deco_add(char *text);
-void deco_cnv(struct deco *dc, struct SYMBOL *s, struct SYMBOL *prev);
-unsigned char deco_intern(unsigned char deco);
-unsigned char deco_define(char *name);
-void deco_update(struct SYMBOL *s, float dx);
-float deco_width(struct SYMBOL *s);
-void draw_all_deco(void);
-int draw_deco_head(int deco, float x, float y, int stem);
-void draw_all_deco_head(struct SYMBOL *s, float x, float y);
-void draw_deco_near(void);
-void draw_deco_note(void);
-void draw_deco_staff(void);
-float draw_partempo(int staff, float top);
-void draw_measnb(void);
-void reset_deco(void);
-void set_defl(int new_defl);
-float tempo_width(struct SYMBOL *s);
-void write_tempo(struct SYMBOL *s,
- int beat,
- float sc);
-float y_get(int staff,
- int up,
- float x,
- float w);
-void y_set(int staff,
- int up,
- float x,
- float w,
- float y);
-/* draw.c */
-void draw_sym_near(void);
-void draw_all_symb(void);
-float draw_systems(float indent);
-void output_ps(struct SYMBOL *s, int state);
-void putf(float f);
-void putx(float x);
-void puty(float y);
-void putxy(float x, float y);
-void set_scale(struct SYMBOL *s);
-void set_sscale(int staff);
-/* format.c */
-void define_fonts(void);
-int get_textopt(char *p);
-int get_font_encoding(int ft);
-void interpret_fmt_line(char *w, char *p, int lock);
-void lock_fmt(void *fmt);
-void make_font_list(void);
-FILE *open_file(char *fn,
- char *ext,
- char *rfn);
-void print_format(void);
-void set_font(int ft);
-void set_format(void);
-void set_voice_param(struct VOICE_S *p_voice, int state, char *w, char *p);
-struct tblt_s *tblt_parse(char *p);
-/* glyph.c */
-char *glyph_out(char *p);
-void glyph_add(char *p);
-/* music.c */
-void output_music(void);
-void reset_gen(void);
-void unlksym(struct SYMBOL *s);
-/* parse.c */
-extern float multicol_start;
-void do_tune(struct abctune *t);
-void identify_note(struct SYMBOL *s,
- int len,
- int *p_head,
- int *p_dots,
- int *p_flags);
-void sort_pitch(struct SYMBOL *s, int combine);
-struct SYMBOL *sym_add(struct VOICE_S *p_voice,
- int type);
-/* subs.c */
-void bug(char *msg, int fatal);
-void error(int sev, struct SYMBOL *s, char *fmt, ...);
-float scan_u(char *str);
-float cwid(unsigned short c);
-void get_str_font(int *cft, int *dft);
-void set_str_font(int cft, int dft);
-#ifdef HAVE_PANGO
-void pg_init(void);
-void pg_reset_font(void);
-#endif
-void put_history(void);
-void put_words(struct SYMBOL *words);
-void str_font(int ft);
-#define A_LEFT 0
-#define A_CENTER 1
-#define A_RIGHT 2
-#define A_LYRIC 3
-#define A_GCHORD 4
-#define A_ANNOT 5
-#define A_GCHEXP 6
-void str_out(char *p, int action);
-void put_str(char *str, int action);
-float tex_str(char *s);
-extern char tex_buf[]; /* result of tex_str() */
-#define TEX_BUF_SZ 512
-char *trim_title(char *p, struct SYMBOL *title);
-void user_ps_add(char *s, char use);
-void user_ps_write(void);
-void write_title(struct SYMBOL *s);
-void write_heading(struct abctune *t);
-void write_user_ps(void);
-void write_text(char *cmd, char *s, int job);
-/* svg.c */
-void define_svg_symbols(char *title, int num, float w, float h);
-int svg_output(FILE *out, const char *fmt, ...)
-#ifdef __GNUC__
- __attribute__ ((format (printf, 2, 3)))
-#endif
- ;
-void svg_write(char *buf, int len);
-void svg_close();
-/* syms.c */
-void define_font(char *name, int num, int enc);
-void define_symbols(void);
Binary files /tmp/tmputFabm/2sug4RLyYU/abcm2ps-7.8.9/abc2svg.ttf and /tmp/tmputFabm/amw0CNkIJH/abcm2ps-8.14.2/abc2svg.ttf differ
diff -Nru abcm2ps-7.8.9/abcm2ps.c abcm2ps-8.14.2/abcm2ps.c
--- abcm2ps-7.8.9/abcm2ps.c 1970-01-01 00:00:00.000000000 +0000
+++ abcm2ps-8.14.2/abcm2ps.c 2018-12-18 15:18:26.000000000 +0000
@@ -0,0 +1,1118 @@
+/*
+ * abcm2ps: a program to typeset tunes written in ABC format
+ * using PostScript or SVG
+ *
+ * Copyright (C) 1998-2017 Jean-François Moine (http://moinejf.free.fr)
+ *
+ * Adapted from abc2ps-1.2.5:
+ * Copyright (C) 1996,1997 Michael Methfessel (msm@ihp-ffo.de)
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+#include "abcm2ps.h"
+
+#ifdef HAVE_MMAP
+#include
+#include
+#elif defined(linux)
+#include
+#endif
+
+/* -- global variables -- */
+
+INFO info;
+struct SYMBOL *sym; /* (points to the symbols of the current voice) */
+
+int tunenum; /* number of current tune */
+int pagenum = 1; /* current page in output file */
+int pagenum_nr = 1; /* current page (non-resettable) */
+
+ /* switches modified by command line flags: */
+int quiet; /* quiet mode */
+int secure; /* secure mode */
+int annotate; /* output source references */
+int pagenumbers; /* write page numbers */
+int epsf; /* 1: EPSF, 2: SVG, 3: embedded ABC */
+int svg; /* 1: SVG, 2: XHTML */
+int showerror; /* show the errors */
+int pipeformat = 0; /* format for bagpipes regardless of key */
+
+char outfn[FILENAME_MAX]; /* output file name */
+int file_initialized; /* for output file */
+FILE *fout; /* output file */
+char *in_fname; /* top level input file name */
+time_t mtime; /* last modification time of the input file */
+static time_t fmtime; /* " " of all files */
+
+int s_argc; /* command line arguments */
+char **s_argv;
+
+struct tblt_s *tblts[MAXTBLT];
+struct cmdtblt_s cmdtblts[MAXCMDTBLT];
+int ncmdtblt;
+
+/* -- local variables -- */
+
+static char *styd = DEFAULT_FDIR; /* format search directory */
+static int def_fmt_done = 0; /* default format read */
+static struct SYMBOL notitle;
+
+/* memory arena (for clrarena, lvlarena & getarena) */
+#define MAXAREAL 3 /* max area levels:
+ * 0; global, 1: tune, 2: generation */
+#define AREANASZ 0x4000 /* standard allocation size */
+#define MAXAREANASZ 0x20000 /* biggest allocation size */
+static int str_level; /* current arena level */
+static struct str_a {
+ struct str_a *n; /* next area */
+ char *p; /* pointer in area */
+ int r; /* remaining space in area */
+ int sz; /* size of str[] */
+ char str[2]; /* start of memory area */
+} *str_r[MAXAREAL], *str_c[MAXAREAL]; /* root and current area pointers */
+
+/* -- local functions -- */
+static void read_def_format(void);
+
+static FILE *open_ext(char *fn, char *ext)
+{
+ FILE *fp;
+ char *p;
+
+ if ((fp = fopen(fn, "rb")) != NULL)
+ return fp;
+ if ((p = strrchr(fn, DIRSEP)) == NULL)
+ p = fn;
+ if (strrchr(p, '.') != NULL)
+ return NULL;
+ strcat(p, ".");
+ strcat(p, ext);
+ if ((fp = fopen(fn, "rb")) != NULL)
+ return fp;
+ return NULL;
+}
+
+/* -- open a file for reading -- */
+FILE *open_file(char *fn, /* file name */
+ char *ext, /* file type */
+ char *rfn) /* returned real file name */
+{
+ FILE *fp;
+ char *p;
+ int l;
+
+ /* if there was some ABC file, try its directory */
+ if (in_fname && in_fname != fn
+ && (p = strrchr(in_fname, DIRSEP)) != NULL) {
+ l = p - in_fname + 1;
+ strncpy(rfn, in_fname, l);
+ strcpy(&rfn[l], fn);
+ if ((fp = open_ext(rfn, ext)) != NULL)
+ return fp;
+ }
+
+ /* try locally */
+ strcpy(rfn, fn);
+ if ((fp = open_ext(rfn, ext)) != NULL)
+ return fp;
+
+ /* try a format in the format directory */
+ if (*ext != 'f' || *styd == '\0')
+ return NULL;
+ l = strlen(styd) - 1;
+ if (styd[l] == DIRSEP)
+ sprintf(rfn, "%s%s", styd, fn);
+ else
+ sprintf(rfn, "%s%c%s", styd, DIRSEP, fn);
+ return open_ext(rfn, ext);
+}
+
+/* -- read a whole input file -- */
+/* return the real/full file name in tex_buf[] */
+static char *read_file(char *fn, char *ext)
+{
+ size_t fsize;
+ FILE *fin;
+ char *file;
+
+ if (*fn == '\0') {
+ strcpy(tex_buf, "stdin");
+ fsize = 0;
+ file = malloc(8192);
+ for (;;) {
+ int l;
+
+ l = fread(&file[fsize], 1, 8192, stdin);
+ fsize += l;
+ if (l != 8192)
+ break;
+ file = realloc(file, fsize + 8192);
+ }
+ if (ferror(stdin) != 0) {
+ free(file);
+ return 0;
+ }
+ if (fsize % 8192 == 0)
+ file = realloc(file, fsize + 2);
+ time(&fmtime);
+ } else {
+ struct stat sbuf;
+
+ fin = open_file(fn, ext, tex_buf);
+ if (!fin)
+ return NULL;
+ if (fseek(fin, 0L, SEEK_END) < 0) {
+ fclose(fin);
+ return NULL;
+ }
+ fsize = ftell(fin);
+ rewind(fin);
+ if ((file = malloc(fsize + 2)) == NULL) {
+ fclose(fin);
+ return NULL;
+ }
+
+ if (fread(file, 1, fsize, fin) != fsize) {
+ fclose(fin);
+ free(file);
+ return NULL;
+ }
+ fstat(fileno(fin), &sbuf);
+ memcpy(&fmtime, &sbuf.st_mtime, sizeof fmtime);
+ fclose(fin);
+ }
+ file[fsize] = '\0';
+ return file;
+}
+
+/* -- treat an input file and generate the ABC file -- */
+static void treat_file(char *fn, char *ext)
+{
+ char *file;
+ char *abc_fn;
+ int file_type, l;
+
+ /* initialize if not already done */
+ if (!fout) {
+ read_def_format();
+ if (strcmp(fn, tex_buf) == 0)
+ return; // if xx.default.fmt, done
+ }
+
+ /* read the file into memory */
+ /* the real/full file name is put in tex_buf[] */
+ if ((file = read_file(fn, ext)) == NULL) {
+ if (strcmp(fn, "default.fmt") != 0) {
+ error(1, NULL, "Cannot read the input file '%s'", fn);
+#if defined(unix) || defined(__unix__)
+ perror(" read_file");
+#endif
+ }
+ return;
+ }
+ abc_fn = strdup(tex_buf);
+ if (!quiet)
+ fprintf(strcmp(outfn, "-") == 0 ? stderr : stdout,
+ "File %s\n", abc_fn);
+
+ /* convert the strings */
+ l = strlen(abc_fn);
+ if (strcmp(&abc_fn[l - 3], ".ps") == 0) {
+ file_type = FE_PS;
+ } else if (strcmp(&abc_fn[l - 4], ".fmt") == 0) {
+ file_type = FE_FMT;
+ } else {
+ file_type = FE_ABC;
+// in_fname = abc_fn;
+ mtime = fmtime;
+ }
+
+ frontend((unsigned char *) file, file_type,
+ abc_fn, 0);
+ free(file);
+
+ if (file_type == FE_PS) /* PostScript file */
+ frontend((unsigned char *) "%%endps", FE_ABC,
+ abc_fn, 0);
+ if (file_type == FE_ABC) /* if ABC file */
+ clrarena(1); /* clear previous tunes */
+}
+
+/* call back to handle %%format/%%abc-include - see front.c */
+void include_file(unsigned char *fn)
+{
+ static int nbfiles;
+
+ if (nbfiles > 2) {
+ error(1, NULL, "Too many included files");
+ return;
+ }
+
+ nbfiles++;
+ treat_file((char *) fn, "fmt");
+ nbfiles--;
+}
+
+/* -- treat an ABC input file and generate the music -- */
+/* this function also treats ABC in XHTML */
+static void treat_abc_file(char *fn)
+{
+ FILE *fin;
+ char *file, *file_tmp;
+ char *abc_fn, *p, *q;
+ size_t fsize, l, l2;
+ int linenum;
+#ifdef HAVE_MMAP
+ int fd;
+#endif
+
+ lvlarena(0);
+ parse.abc_state = ABC_S_GLOBAL;
+
+ if (epsf != 3) {
+ treat_file(fn, "abc"); /* not '-z' */
+ return;
+ }
+
+ if (*fn == '\0') {
+ error(1, NULL, "cannot use stdin with -z - aborting");
+ exit(EXIT_FAILURE);
+ }
+
+ fin = open_file(fn, "abc", tex_buf);
+ if (!fin)
+ goto err;
+ if (fseek(fin, 0L, SEEK_END) < 0) {
+ fclose(fin);
+ goto err;
+ }
+ fsize = ftell(fin);
+ rewind(fin);
+#ifdef HAVE_MMAP
+ fd = fileno(fin);
+ file = mmap(NULL, fsize, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (!file)
+ goto err;
+#else
+ file = malloc(fsize);
+ if (!file)
+ goto err;
+ if (fread(file, 1, fsize, fin) != fsize) {
+ free(file);
+ goto err;
+ }
+ fclose(fin);
+#endif
+
+ /* copy the HTML/XML/XHTML file and generate the music */
+ abc_fn = strdup(tex_buf);
+ l = fsize;
+ p = file;
+ linenum = 0;
+ while (l > 0) {
+
+ /* search the start of ABC lines */
+#if 1
+ for (q = p, l2 = l - 10; l2 > 0; l2--, q++) {
+ if (strncmp(q, "\n%abc", 5) == 0
+// || strncmp(q, "\n%%", 3) == 0
+ || strncmp(q, "\nX:", 3) == 0)
+ break;
+ }
+#else
+ for (q = p, l2 = l - 5; l2 > 0; l2--, q++)
+ if (strncmp(q, "", 5) == 0)
+ break;
+#endif
+ if (l2 <= 0) {
+ fwrite(p, 1, l, fout);
+ break;
+ }
+ q++;
+ fwrite(p, 1, q - p, fout);
+ l -= q - p;
+ while (p != q) {
+ if (*p++ == '\n')
+ linenum++;
+ }
+
+ /* search the end of ABC lines */
+ for (q = p, l2 = l - 10; l2 > 0; l2--, q++)
+ if (*q == '\n' && q[1] == '<')
+ break;
+ if (l2 <= 0) {
+ error(1, NULL, "no end of ABC sequence");
+ q += 9;
+// break;
+ }
+ q++;
+
+ /* must copy ... :( */
+ l2 = q - p;
+ file_tmp = malloc(l2 + 1);
+ if (!file_tmp) {
+ error(1, NULL, "out of memory");
+ break;
+ }
+ memcpy(file_tmp, p, l2);
+ file_tmp[l2] = '\0';
+
+ frontend((unsigned char *) file_tmp, FE_ABC,
+ abc_fn, linenum);
+ free(file_tmp);
+
+ clrarena(1); /* clear previous tunes */
+ file_initialized = -1; /* don't put
before first image */
+
+ l -= q - p;
+ while (p != q) {
+ if (*p++ == '\n')
+ linenum++;
+ }
+ }
+
+#ifdef HAVE_MMAP
+ munmap(file, fsize);
+ fclose(fin);
+#else
+ free(file);
+#endif
+ return;
+err:
+ error(1, NULL, "input file %s error %s - aborting", fn, strerror(errno));
+ exit(EXIT_FAILURE);
+}
+
+/* -- read the default format -- */
+static void read_def_format(void)
+{
+ if (def_fmt_done)
+ return;
+ def_fmt_done = 1;
+ treat_file("default.fmt", "fmt");
+}
+
+/* -- set extension on a file name -- */
+void strext(char *fn, char *ext)
+{
+ char *p, *q;
+
+ if ((p = strrchr(fn, DIRSEP)) == NULL)
+ p = fn;
+ if ((q = strrchr(p, '.')) == NULL)
+ strcat(p, ".");
+ else
+ q[1] = '\0';
+ strcat(p, ext);
+}
+
+/* -- write the program version -- */
+static void display_version(int full)
+{
+ FILE *log = strcmp(outfn, "-") == 0 ? stderr : stdout;
+
+ fputs("abcm2ps-" VERSION " (" VDATE ")\n", log);
+ if (!full)
+ return;
+ fputs("Options:"
+#ifdef A4_FORMAT
+ " A4_FORMAT"
+#endif
+#ifdef DECO_IS_ROLL
+ " DECO_IS_ROLL"
+#endif
+#ifdef HAVE_PANGO
+ " PANGO"
+#endif
+#if !defined(A4_FORMAT) && !defined(DECO_IS_ROLL) && !defined(HAVE_PANGO)
+ " NONE"
+#endif
+ "\n", log);
+ if (styd[0] != '\0')
+ fprintf(log, "Default format directory: %s\n", styd);
+}
+
+/* -- display usage and exit -- */
+static void usage(void)
+{
+ display_version(0);
+ printf( "ABC to Postscript/SVG translator.\n"
+ "Usage: abcm2ps [options] file [file_options] ..\n"
+ "where:\n"
+ " file input ABC file, or '-'\n"
+ " options and file_options:\n"
+ " .output file options:\n"
+ " -E produce EPSF output, one tune per file\n"
+ " -g produce SVG output, one tune per file\n"
+ " -v produce SVG output, one page per file\n"
+ " -X produce SVG output in one XHTML file\n"
+ " -z produce SVG output from embedded ABC\n"
+ " -O fff set outfile name to fff\n"
+ " -O = make outfile name from infile/title\n"
+ " -i indicate where are the errors\n"
+ " -k kk size of the PS output buffer in Kibytes\n"
+ " .output formatting:\n"
+ " -s xx set scale factor to xx\n"
+ " -w xx set staff width (cm/in/pt)\n"
+ " -m xx set left margin (cm/in/pt)\n"
+ " -d xx set staff separation (cm/in/pt)\n"
+ " -a xx set max shrinkage to xx (between 0 and 1)\n"
+ " -F foo read format file \"foo.fmt\"\n"
+ " -D bar look for format files in directory \"bar\"\n"
+ " -p format for bagpipes regardless of key\n"
+ " .output options:\n"
+ " -l landscape mode\n"
+ " -I xx indent 1st line (cm/in/pt)\n"
+ " -x add xref numbers in titles\n"
+ " -M don't output the lyrics\n"
+ " -N n set page numbering mode to n=\n"
+ " 0=off 1=left 2=right 3=even left,odd right 4=even right,odd left\n"
+ " -1 write one tune per page\n"
+ " -G no slur in grace notes\n"
+ " -j n[b] number the measures every n bars (or on the left if n=0)\n"
+ " if 'b', display in a box\n"
+ " -b n set the first measure number to n\n"
+ " -f have flat beams\n"
+ " -T n[v] output the tablature 'n' for voice 'v' / all voices\n"
+ " .line breaks:\n"
+ " -c auto line break\n"
+ " -B n break every n bars\n"
+ " .input file selection/options:\n"
+ " -e pattern\n"
+ " tune selection\n"
+ " .help/configuration:\n"
+ " -V show program version\n"
+ " -h show this command summary\n"
+ " -H show the format parameters\n"
+ " -S secure mode\n"
+ " -q quiet mode\n");
+ exit(EXIT_SUCCESS);
+}
+
+#ifdef linux
+/* -- where is the default format directory -- */
+static void wherefmtdir(void)
+{
+ char exe[512], *p;
+ FILE *f;
+ int l;
+
+ if ((l = readlink("/proc/self/exe", exe, sizeof exe)) <= 0)
+ return;
+ if ((p = strrchr(exe, '/')) == NULL)
+ return;
+ p++;
+ if (p > &exe[5] && strncmp(p - 5, "/bin", 4) == 0) {
+ strcpy(p - 4, "share/abcm2ps/");
+ p += -4 + 14;
+ }
+ /* else, assume this is the source directory */
+
+ /* check if a format file is present */
+ strcpy(p, "tight.fmt");
+ if ((f = fopen(exe, "r")) == NULL)
+ return;
+ fclose(f);
+
+ /* change the format directory */
+ p[-1] = '\0';
+ styd = strdup(exe);
+}
+#endif
+
+/* -- parse the tablature command ('-T n[v]') -- */
+static struct cmdtblt_s *cmdtblt_parse(char *p)
+{
+ struct cmdtblt_s *cmdtblt;
+ short val;
+
+ if (ncmdtblt >= MAXCMDTBLT) {
+ error(1, NULL, "++++ Too many '-T'");
+ return NULL;
+ }
+ if (*p == '\0')
+ val = -1;
+ else {
+ val = *p++ - '0' - 1;
+ if ((unsigned) val > MAXTBLT) {
+ error(1, NULL, "++++ Bad tablature number in '-T'\n");
+ return 0;
+ }
+ }
+ cmdtblt = &cmdtblts[ncmdtblt++];
+ cmdtblt->index = val;
+ cmdtblt->vn = p;
+ return cmdtblt;
+}
+
+/* set a command line option */
+static void set_opt(char *w, char *v)
+{
+ static char prefix = '%'; /* pseudo-comment prefix */
+
+ if (!v)
+ v = "";
+ if (strlen(w) + strlen(v) >= TEX_BUF_SZ - 10) {
+ error(1, NULL, "Command line '%s' option too long", w);
+ return;
+ }
+ sprintf(tex_buf, /* this buffer is available */
+ "%%%c%s %s lock\n", prefix, w, v);
+ if (strcmp(w, "abcm2ps") == 0)
+ prefix = *v;
+ frontend((unsigned char *) tex_buf, FE_ABC,
+ "cmd_line", 0);
+}
+
+/* -- main program -- */
+int main(int argc, char **argv)
+{
+ unsigned j;
+ char *p, c, *aaa;
+
+ if (argc <= 1)
+ usage();
+
+ outfn[0] = '\0';
+ init_outbuf(64);
+
+ /* set the global flags */
+ s_argc = argc;
+ s_argv = argv;
+ aaa = NULL;
+ while (--argc > 0) {
+ argv++;
+ p = *argv;
+ if (*p != '-' || p[1] == '-') {
+ if (*p == '+' && p[1] == 'F') /* +F : no default format */
+ def_fmt_done = 1;
+ continue;
+ }
+ while ((c = *++p) != '\0') { /* '-xxx' */
+ switch (c) {
+ case 'E':
+ svg = 0; /* EPS */
+ epsf = 1;
+ break;
+ case 'g':
+ svg = 0; /* SVG one file per tune */
+ epsf = 2;
+ break;
+ case 'H':
+ quiet = 1; // don't output the version
+ break;
+ case 'h':
+ usage(); /* no return */
+ case 'p':
+ pipeformat = 1; /* format for bagpipe regardless of key */
+ break;
+ case 'q':
+ quiet = 1;
+ break;
+ case 'S':
+ secure = 1;
+ break;
+ case 'V':
+ display_version(1);
+ return EXIT_SUCCESS;
+ case 'v':
+ svg = 1; /* SVG one file per page */
+ epsf = 0;
+ break;
+ case 'X':
+ svg = 2; /* SVG/XHTML */
+ epsf = 0;
+ break;
+ case 'k': {
+ int kbsz;
+
+ if (p[1] == '\0') {
+ if (--argc <= 0) {
+ error(1, NULL, "No value for '-k' - aborting");
+ return EXIT_FAILURE;
+ }
+ aaa = *++argv;
+ } else {
+ aaa = p + 1;
+ p += strlen(p) - 1;
+ }
+
+ sscanf(aaa, "%d", &kbsz);
+ init_outbuf(kbsz);
+ break;
+ }
+ case 'O':
+ if (p[1] == '\0') {
+ if (--argc <= 0) {
+ error(1, NULL, "No value for '-O' - aborting");
+ return EXIT_FAILURE;
+ }
+ aaa = *++argv;
+ } else {
+ aaa = p + 1;
+ p += strlen(p) - 1;
+ }
+ if (strlen(aaa) >= sizeof outfn) {
+ error(1, NULL, "'-O' too large - aborting");
+ return EXIT_FAILURE;
+ }
+ strcpy(outfn, aaa);
+ break;
+ case 'z':
+ epsf = 3; /* ABC embedded in XML */
+ svg = 0;
+ break;
+ default:
+ if (strchr("aBbDdeFfIjmNOsTw", c)) /* if with arg */
+ p += strlen(p) - 1; /* skip */
+ break;
+ }
+ }
+ }
+ if (!quiet)
+ display_version(0);
+
+ /* initialize */
+ clrarena(0); /* global */
+ clrarena(1); /* tunes */
+ clrarena(2); /* generation */
+// memset(&info, 0, sizeof info);
+ info['T' - 'A'] = ¬itle;
+ notitle.text = "T:";
+ set_format();
+ init_deco();
+
+#ifdef linux
+ /* if not set, try to find where is the default format directory */
+ if (styd[0] == '\0')
+ wherefmtdir();
+#endif
+#ifdef HAVE_PANGO
+ pg_init();
+#endif
+
+ /* if ABC embedded in XML, open the output file */
+ if (epsf == 3) {
+ open_fout();
+ read_def_format();
+ }
+
+ /* parse the arguments - finding a new file, treat the previous one */
+ argc = s_argc;
+ argv = s_argv;
+ while (--argc > 0) {
+ argv++;
+ p = *argv;
+ if ((c = *p) == '\0')
+ continue;
+ if (c == '-') {
+ int i;
+
+ if (p[1] == '\0') { /* '-' alone */
+ if (in_fname) {
+ treat_abc_file(in_fname);
+ frontend((unsigned char *) "select\n", FE_FMT,
+ "cmd_line", 0);
+ }
+ in_fname = ""; /* read from stdin */
+ continue;
+ }
+ i = strlen(p) - 1;
+ if (p[i] == '-'
+ && p[1] != '-'
+//fixme: 'e' may be preceded by other options
+ && p[1] != 'e'
+ && p[i -1] != 'O')
+ c = '+'; /* switch off flags with '-x-' */
+ }
+ if (c == '+') { /* switch off flags with '+' */
+ while (*++p != '\0') {
+ switch (*p) {
+ case '-':
+ break;
+ case 'B':
+ cfmt.barsperstaff = 0;
+ lock_fmt(&cfmt.barsperstaff);
+ break;
+ case 'c':
+ cfmt.continueall = 0;
+ lock_fmt(&cfmt.continueall);
+ break;
+ case 'F':
+// def_fmt_done = 1;
+ break;
+ case 'G':
+ cfmt.graceslurs = 1;
+ lock_fmt(&cfmt.graceslurs);
+ break;
+ case 'i':
+ showerror = 0;
+ break;
+ case 'j':
+ cfmt.measurenb = -1;
+ lock_fmt(&cfmt.measurenb);
+ break;
+ case 'l':
+ cfmt.landscape = 0;
+ lock_fmt(&cfmt.landscape);
+ break;
+ case 'M':
+ cfmt.fields[1] = 1 << ('w' - 'a');
+ lock_fmt(&cfmt.fields);
+ break;
+ case 'N':
+ pagenumbers = 0;
+ break;
+ case 'O':
+ outfn[0] = '\0';
+ break;
+ case 'T': {
+ struct cmdtblt_s *cmdtblt;
+
+ aaa = p + 1;
+ if (*aaa == '\0') {
+ if (argc > 1
+ && argv[1][0] != '-') {
+ aaa = *++argv;
+ argc--;
+ }
+ } else {
+ while (p[1] != '\0') /* stop */
+ p++;
+ if (*p == '-')
+ *p-- = '\0'; /* (not clean) */
+ }
+ cmdtblt = cmdtblt_parse(aaa);
+ if (cmdtblt != 0)
+ cmdtblt->active = 0;
+ break;
+ }
+ case 'x':
+ cfmt.fields[0] &= ~(1 << ('X' - 'A'));
+ lock_fmt(&cfmt.fields);
+ break;
+ case '0':
+ cfmt.splittune = 0;
+ lock_fmt(&cfmt.splittune);
+ break;
+ case '1':
+ cfmt.oneperpage = 0;
+ lock_fmt(&cfmt.oneperpage);
+ break;
+ default:
+ error(1, NULL,
+ "++++ Cannot switch off flag: +%c",
+ *p);
+ break;
+ }
+ }
+ continue;
+ }
+
+ if (c == '-') { /* interpret a flag with '-' */
+ if (p[1] == '-') { /* long argument */
+ p += 2;
+ if (--argc <= 0) {
+ error(1, NULL, "No argument for '--'");
+ return EXIT_FAILURE;
+ }
+ argv++;
+ set_opt(p, *argv);
+ continue;
+ }
+ while ((c = *++p) != '\0') {
+ switch (c) {
+
+ /* simple flags */
+ case 'A':
+ annotate = 1;
+ break;
+ case 'c':
+ cfmt.continueall = 1;
+ lock_fmt(&cfmt.continueall);
+ break;
+ case 'E':
+ break;
+ case 'f':
+ cfmt.flatbeams = 1;
+ lock_fmt(&cfmt.flatbeams);
+ break;
+ case 'G':
+ cfmt.graceslurs = 0;
+ lock_fmt(&cfmt.graceslurs);
+ break;
+ case 'g':
+ break;
+ case 'H':
+ if (!fout) {
+ read_def_format();
+ make_font_list();
+ do_tune();
+ }
+ print_format();
+ return EXIT_SUCCESS;
+ case 'i':
+ showerror = 1;
+ break;
+ case 'l':
+ cfmt.landscape = 1;
+ lock_fmt(&cfmt.landscape);
+ break;
+ case 'M':
+ cfmt.fields[1] &= ~(1 << ('w' - 'a'));
+ lock_fmt(&cfmt.fields);
+ break;
+ case 'p':
+ case 'q':
+ case 'S':
+ break;
+ case 'v':
+ case 'X':
+ case 'z':
+ break;
+ case 'x':
+ cfmt.fields[0] |= 1 << ('X' - 'A');
+ lock_fmt(&cfmt.fields);
+ break;
+ case '0':
+ cfmt.splittune = 1;
+ lock_fmt(&cfmt.splittune);
+ break;
+ case '1':
+ cfmt.oneperpage = 1;
+ lock_fmt(&cfmt.oneperpage);
+ break;
+
+ /* flag with optional parameter */
+ case 'N':
+ if (p[1] == '\0'
+ && (argc <= 1
+ || !isdigit((unsigned) argv[1][0]))) {
+ pagenumbers = 2; /* old behaviour */
+ break;
+ }
+ /* fall thru */
+ /* flags with parameter.. */
+ case 'a':
+ case 'B':
+ case 'b':
+ case 'D':
+ case 'd':
+ case 'e':
+ case 'F':
+ case 'I':
+ case 'j':
+ case 'k':
+ case 'L':
+ case 'm':
+ case 'O':
+ case 's':
+ case 'T':
+ case 'w':
+ aaa = p + 1;
+ if (*aaa == '\0') {
+ aaa = *++argv;
+ if (--argc <= 0
+ || (*aaa == '-' && c != 'O')) {
+ error(1, NULL,
+ "Missing parameter after '-%c' - aborting",
+ c);
+ return EXIT_FAILURE;
+ }
+ } else {
+ p += strlen(p) - 1; /* stop */
+ }
+
+ if (strchr("BbfjkNs", c)) { /* check num args */
+ for (j = 0; j < strlen(aaa); j++) {
+ if (!strchr("0123456789.",
+ aaa[j])) {
+ if (aaa[j] == 'b'
+ && aaa[j + 1] == '\0'
+ && c == 'j')
+ break;
+ error(1, NULL,
+ "Invalid parameter <%s> for flag -%c",
+ aaa, c);
+ return EXIT_FAILURE;
+ }
+ }
+ }
+
+ switch (c) {
+ case 'a':
+ set_opt("maxshrink", aaa);
+ break;
+ case 'B':
+ set_opt("barsperstaff", aaa);
+ break;
+ case 'b':
+ set_opt("measurefirst", aaa);
+ break;
+ case 'D':
+ styd = aaa;
+ break;
+ case 'd':
+ set_opt("staffsep", aaa);
+ break;
+ case 'e':
+ set_opt("select", aaa);
+ break;
+ case 'F':
+ treat_file(aaa, "fmt");
+ break;
+ case 'I':
+ set_opt("indent", aaa);
+ break;
+ case 'j':
+ sscanf(aaa, "%d", &cfmt.measurenb);
+ lock_fmt(&cfmt.measurenb);
+ if (aaa[strlen(aaa) - 1] == 'b')
+ cfmt.measurebox = 1;
+ else
+ cfmt.measurebox = 0;
+ lock_fmt(&cfmt.measurebox);
+ break;
+ case 'k':
+ break;
+ case 'm':
+ set_opt("leftmargin", aaa);
+ break;
+ case 'N':
+ sscanf(aaa, "%d", &pagenumbers);
+ if ((unsigned) pagenumbers > 4) {
+ error(1, NULL,
+ "'-N' value %s - changed to 2",
+ aaa);
+ pagenumbers = 2;
+ }
+ break;
+ case 'O':
+ if (strlen(aaa) >= sizeof outfn) {
+ error(1, NULL, "'-O' too large - aborting");
+ exit(EXIT_FAILURE);
+ }
+ strcpy(outfn, aaa);
+ break;
+ case 's':
+ set_opt("scale", aaa);
+ break;
+ case 'T': {
+ struct cmdtblt_s *cmdtblt;
+
+ cmdtblt = cmdtblt_parse(aaa);
+ if (cmdtblt)
+ cmdtblt->active = 1;
+ break;
+ }
+ case 'w':
+ set_opt("staffwidth", aaa);
+ break;
+ }
+ break;
+ default:
+ error(1, NULL,
+ "Unknown flag: -%c ignored", c);
+ break;
+ }
+ }
+ continue;
+ }
+
+ if (in_fname) {
+ treat_abc_file(in_fname);
+ frontend((unsigned char *) "select\n", FE_FMT,
+ "cmd_line", 0);
+ }
+ in_fname = p;
+ }
+
+ if (in_fname)
+ treat_abc_file(in_fname);
+ if (multicol_start != 0) { /* lack of %%multicol end */
+ error(1, NULL, "Lack of %%%%multicol end");
+ multicol_start = 0;
+ buffer_eob(0);
+ if (!info['X' - 'A']
+ && !epsf)
+ write_buffer();
+ }
+ if (!epsf && !fout) {
+ error(1, NULL, "Nothing to generate!");
+ return EXIT_FAILURE;
+ }
+ close_output_file();
+ return severity == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+/* -- arena routines -- */
+void clrarena(int level)
+{
+ struct str_a *a_p;
+
+ if ((a_p = str_r[level]) == NULL) {
+ str_r[level] = a_p = malloc(sizeof *str_r[0] + AREANASZ - 2);
+ a_p->sz = AREANASZ;
+ a_p->n = NULL;
+ }
+ str_c[level] = a_p;
+ a_p->p = a_p->str;
+ a_p->r = a_p->sz;
+}
+
+int lvlarena(int level)
+{
+ int old_level;
+
+ old_level = str_level;
+ str_level = level;
+ return old_level;
+}
+
+/* The area is 8 bytes aligned to handle correctly int and pointers access
+ * on some machines as Sun Sparc. */
+void *getarena(int len)
+{
+ char *p;
+ struct str_a *a_p;
+
+ a_p = str_c[str_level];
+ len = (len + 7) & ~7; /* align at 64 bits boundary */
+ if (len > a_p->r) {
+ if (len > MAXAREANASZ) {
+ error(1, NULL,
+ "getarena - data too wide %d - aborting",
+ len);
+ exit(EXIT_FAILURE);
+ }
+ if (len > AREANASZ) { /* big allocation */
+ struct str_a *a_n;
+
+ a_n = a_p->n;
+ a_p->n = malloc(sizeof *str_r[0] + len - 2);
+ a_p->n->n = a_n;
+ a_p->n->sz = len;
+ } else if (a_p->n == 0) { /* standard allocation */
+ a_p->n = malloc(sizeof *str_r[0] + AREANASZ - 2);
+ a_p->n->n = NULL;
+ a_p->n->sz = AREANASZ;
+ }
+ str_c[str_level] = a_p = a_p->n;
+ a_p->p = a_p->str;
+ a_p->r = a_p->sz;
+ }
+ p = a_p->p;
+ a_p->p += len;
+ a_p->r -= len;
+ return p;
+}
diff -Nru abcm2ps-7.8.9/abcm2ps.h abcm2ps-8.14.2/abcm2ps.h
--- abcm2ps-7.8.9/abcm2ps.h 1970-01-01 00:00:00.000000000 +0000
+++ abcm2ps-8.14.2/abcm2ps.h 2018-12-18 15:18:26.000000000 +0000
@@ -0,0 +1,903 @@
+/* -- general macros -- */
+
+#include
+#include
+
+#include "config.h"
+
+#define MAXVOICE 32 /* max number of voices */
+
+#define MAXHD 8 /* max heads in a chord */
+#define MAXDC 32 /* max decorations per symbol */
+#define MAXMICRO 32 /* max microtone values (5 bits in accs[]) */
+#define DC_NAME_SZ 128 /* size of the decoration name table */
+
+#define BASE_LEN 1536 /* basic note length (semibreve or whole note - same as MIDI) */
+
+#define VOICE_ID_SZ 16 /* max size of the voice identifiers */
+
+/* accidentals */
+enum accidentals {
+ A_NULL, /* none */
+ A_SH, /* sharp */
+ A_NT, /* natural */
+ A_FT, /* flat */
+ A_DS, /* double sharp */
+ A_DF /* double flat */
+};
+
+/* bar types - 4 bits per symbol */
+#define B_BAR 1 /* | */
+#define B_OBRA 2 /* [ */
+#define B_CBRA 3 /* ] */
+#define B_COL 4 /* : */
+
+#define B_SINGLE 0x01 /* | single bar */
+#define B_DOUBLE 0x11 /* || thin double bar */
+#define B_THIN_THICK 0x13 /* |] thick at section end */
+#define B_THICK_THIN 0x21 /* [| thick at section start */
+#define B_LREP 0x14 /* |: left repeat bar */
+#define B_RREP 0x41 /* :| right repeat bar */
+#define B_DREP 0x44 /* :: double repeat bar */
+#define B_DASH 0x04 /* : dashed bar */
+
+/* slur/tie types (4 bits) */
+#define SL_ABOVE 0x01
+#define SL_BELOW 0x02
+#define SL_HIDDEN 0x03 /* also opposite for gstemdir */
+#define SL_AUTO 0x04
+#define SL_DOTTED 0x08 /* (modifier bit) */
+
+#define OUTPUTFILE "Out.ps" /* standard output file */
+
+#ifndef WIN32
+#define DIRSEP '/'
+#else
+#define DIRSEP '\\'
+#define strcasecmp stricmp
+#define strncasecmp _strnicmp
+#define strdup _strdup
+#define snprintf _snprintf
+#ifdef _MSC_VER
+#define fileno _fileno
+#endif
+#endif
+
+#define CM * 37.8 /* factor to transform cm to pt */
+#define PT /* factor to transform pt to pt */
+#define IN * 96.0 /* factor to transform inch to pt */
+
+/* basic page dimensions */
+#ifdef A4_FORMAT
+#define PAGEHEIGHT (29.7 CM)
+#define PAGEWIDTH (21.0 CM)
+#define MARGIN (1.8 CM)
+#else
+#define PAGEHEIGHT (11.0 IN)
+#define PAGEWIDTH (8.5 IN)
+#define MARGIN (0.7 IN)
+#endif
+
+/* -- macros controlling music typesetting -- */
+
+#define STEM_YOFF 1.0 /* offset stem from note center */
+#define STEM_XOFF 3.5
+#define STEM 21 /* default stem height = one octave */
+#define STEM_MIN 16 /* min stem height under beams */
+#define STEM_MIN2 14 /* ... for notes with two beams */
+#define STEM_MIN3 12 /* ... for notes with three beams */
+#define STEM_MIN4 10 /* ... for notes with four beams */
+#define STEM_CH_MIN 14 /* min stem height for chords under beams */
+#define STEM_CH_MIN2 10 /* ... for notes with two beams */
+#define STEM_CH_MIN3 9 /* ... for notes with three beams */
+#define STEM_CH_MIN4 9 /* ... for notes with four beams */
+#define BEAM_DEPTH 3.2 /* width of a beam stroke */
+#define BEAM_OFFSET 0.25 /* pos of flat beam relative to staff line */
+#define BEAM_SHIFT 5.0 /* shift of second and third beams */
+/* To align the 4th beam as the 1st: shift=6-(depth-2*offset)/3 */
+#define BEAM_FLATFAC 0.6 /* factor to decrease slope of long beams */
+#define BEAM_THRESH 0.06 /* flat beam if slope below this threshold */
+#define BEAM_SLOPE 0.5 /* max slope of a beam */
+#define BEAM_STUB 7.0 /* length of stub for flag under beam */
+#define SLUR_SLOPE 1.0 /* max slope of a slur */
+#define GSTEM 15 /* grace note stem length */
+#define GSTEM_XOFF 2.3 /* x offset for grace note stem */
+
+#define BETA_C 0.1 /* max expansion for flag -c */
+#define BETA_X 1.0 /* max expansion before complaining */
+
+#define VOCPRE 0.4 /* portion of vocals word before note */
+#define GCHPRE 0.4 /* portion of guitar chord before note */
+
+/* -- Parameters for note spacing -- */
+/* fnn multiplies the spacing under a beam, to compress the notes a bit */
+
+#define fnnp 0.9
+
+/* -- macros for program internals -- */
+
+#define STRL1 256 /* string length for file names */
+#define MAXSTAFF 32 /* max staves */
+#define BSIZE 512 /* buffer size for one input string */
+
+#define BREVE (BASE_LEN * 2) /* double note (square note) */
+#define SEMIBREVE BASE_LEN /* whole note */
+#define MINIM (BASE_LEN / 2) /* half note (white note) */
+#define CROTCHET (BASE_LEN / 4) /* quarter note (black note) */
+#define QUAVER (BASE_LEN / 8) /* 1/8 note */
+#define SEMIQUAVER (BASE_LEN / 16) /* 1/16 note */
+
+#define MAXFONTS 30 /* max number of fonts */
+
+#define T_LEFT 0
+#define T_JUSTIFY 1
+#define T_FILL 2
+#define T_CENTER 3
+#define T_SKIP 4
+#define T_RIGHT 5
+
+#define YSTEP 128 /* number of steps for y offsets */
+
+struct decos { /* decorations */
+ char n; /* whole number of decorations */
+ struct {
+ unsigned char t; /* decoration index */
+ signed char m; /* index in chord when note / -1 */
+ } tm[MAXDC];
+};
+
+struct note_map { /* note mapping */
+ struct note_map *next; /* note linkage */
+ char type; /* map type */
+#define MAP_ONE 0
+#define MAP_OCT 1
+#define MAP_KEY 2
+#define MAP_ALL 3
+ signed char pit; /* note pitch and accidental */
+ unsigned char acc;
+ char *heads; /* comma separated list of note heads */
+ int color; /* color */
+ signed char print_pit; /* print pitch */
+ unsigned char print_acc; /* print acc */
+};
+struct map { /* voice mapping */
+ struct map *next; /* name linkage */
+ char *name;
+ struct note_map *notes; /* mapping of the notes */
+};
+extern struct map *maps; /* note mappings */
+
+struct note { /* note head */
+ int len; /* note duration (# pts in [1] if space) */
+ signed char pit; /* absolute pitch from source - used for ties and map */
+ unsigned char acc; /* code for accidental & index in micro_tb */
+ unsigned char sl1; /* slur start */
+ char sl2; /* number of slur ends */
+ char ti1; /* flag to start tie here */
+ char hlen; /* length of the head string */
+ char invisible; /* alternate note head */
+ float shhd; /* horizontal head shift (#pts if space) */
+ float shac; /* horizontal accidental shift */
+ char *head; /* head */
+ int color; /* heads when note mapping */
+};
+
+struct notes { /* note chord or rest */
+ struct note notes[MAXHD]; /* note heads */
+ unsigned char slur_st; /* slurs starting here (2 bits array) */
+ char slur_end; /* number of slurs ending here */
+ signed char brhythm; /* broken rhythm */
+ unsigned char microscale; /* microtone denominator - 1 */
+ float sdx; /* x offset of the stem */
+ struct decos dc; /* decorations */
+};
+
+extern int severity;
+
+extern char *deco[256];
+
+struct FONTSPEC {
+ int fnum; /* index to font tables in format.c */
+ float size;
+ float swfac;
+};
+extern char *fontnames[MAXFONTS]; /* list of font names */
+
+/* lyrics */
+#define LY_HYPH 0x10 /* replacement character for hyphen */
+#define LY_UNDER 0x11 /* replacement character for underscore */
+#define MAXLY 16 /* max number of lyrics */
+struct lyl {
+ struct FONTSPEC *f; /* font */
+ float w; /* width */
+ float s; /* shift / note */
+ char t[256]; /* word (dummy size) */
+};
+struct lyrics {
+ struct lyl *lyl[MAXLY]; /* ptr to lyric lines */
+};
+
+/* guitar chord / annotations */
+#define MAXGCH 8 /* max number of guitar chords / annotations */
+struct gch {
+ char type; /* ann. char, 'g' gchord, 'r' repeat, '\0' end */
+ unsigned char idx; /* index in as.text */
+ unsigned char font; /* font */
+ char box; /* 1 if in box */
+ float x, y; /* x y offset / note + (top or bottom) of staff */
+ float w; /* width */
+};
+
+/* positions / directions - see SL_xxx */
+struct posit_s {
+ unsigned short dyn:4; /* %%dynamic */
+ unsigned short gch:4; /* %%gchord */
+ unsigned short orn:4; /* %%ornament */
+ unsigned short voc:4; /* %%vocal */
+ unsigned short vol:4; /* %%volume */
+ unsigned short std:4; /* %%stemdir */
+ unsigned short gsd:4; /* %%gstemdir */
+};
+
+/* music element */
+struct SYMBOL { /* struct for a drawable symbol */
+ struct SYMBOL *abc_next, *abc_prev; /* source linkage */
+ struct SYMBOL *next, *prev; /* voice linkage */
+ struct SYMBOL *ts_next, *ts_prev; /* time linkage */
+ struct SYMBOL *extra; /* extra symbols (grace notes, tempo... */
+ char abc_type; /* ABC symbol type */
+#define ABC_T_NULL 0
+#define ABC_T_INFO 1 /* (text[0] gives the info type) */
+#define ABC_T_PSCOM 2
+#define ABC_T_CLEF 3
+#define ABC_T_NOTE 4
+#define ABC_T_REST 5
+#define ABC_T_BAR 6
+#define ABC_T_EOLN 7
+#define ABC_T_MREST 8 /* multi-measure rest */
+#define ABC_T_MREP 9 /* measure repeat */
+#define ABC_T_V_OVER 10 /* voice overlay */
+#define ABC_T_TUPLET 11
+ unsigned char type; /* symbol type */
+#define NO_TYPE 0 /* invalid type */
+#define NOTEREST 1 /* valid symbol types */
+#define SPACE 2
+#define BAR 3
+#define CLEF 4
+#define TIMESIG 5
+#define KEYSIG 6
+#define TEMPO 7
+#define STAVES 8
+#define MREST 9
+#define PART 10
+#define GRACE 11
+#define FMTCHG 12
+#define TUPLET 13
+#define STBRK 14
+#define CUSTOS 15
+#define NSYMTYPES 16
+ unsigned char voice; /* voice (0..nvoice) */
+ unsigned char staff; /* staff (0..nstaff) */
+ unsigned char nhd; /* number of notes in chord - 1 */
+ signed char pits[MAXHD]; /* pitches / clef */
+ int dur; /* main note duration */
+ int time; /* starting time */
+ unsigned int sflags; /* symbol flags */
+#define S_EOLN 0x0001 /* end of line */
+#define S_BEAM_ST 0x0002 /* beam starts here */
+#define S_BEAM_BR1 0x0004 /* 2nd beam must restart here */
+#define S_BEAM_BR2 0x0008 /* 3rd beam must restart here */
+#define S_BEAM_END 0x0010 /* beam ends here */
+#define S_CLEF_AUTO 0x0020 /* auto clef (when clef) */
+#define S_IN_TUPLET 0x0040 /* in a tuplet */
+#define S_TREM2 0x0080 /* tremolo on 2 notes */
+#define S_RRBAR 0x0100 /* right repeat bar (when bar) */
+#define S_XSTEM 0x0200 /* cross-staff stem (when note) */
+#define S_BEAM_ON 0x0400 /* continue beaming */
+#define S_SL1 0x0800 /* some chord slur start */
+#define S_SL2 0x1000 /* some chord slur end */
+#define S_TI1 0x2000 /* some chord tie start */
+#define S_PERC 0x4000 /* percussion */
+#define S_RBSTOP 0x8000 // end of repeat bracket
+#define S_FEATHERED_BEAM 0x00010000 /* feathered beam */
+#define S_REPEAT 0x00020000 /* sequence / measure repeat */
+#define S_NL 0x00040000 /* start of new music line */
+#define S_SEQST 0x00080000 /* start of vertical sequence */
+#define S_SECOND 0x00100000 /* symbol on a secondary voice */
+#define S_FLOATING 0x00200000 /* symbol on a floating voice */
+#define S_NOREPBRA 0x00400000 /* don't print the repeat bracket */
+#define S_TREM1 0x00800000 /* tremolo on 1 note */
+#define S_TEMP 0x01000000 /* temporary symbol */
+#define S_SHIFTUNISON_1 0x02000000 /* %%shiftunison 1 */
+#define S_SHIFTUNISON_2 0x04000000 /* %%shiftunison 2 */
+#define S_NEW_SY 0x08000000 /* staff system change (%%staves) */
+#define S_RBSTART 0x10000000 // start of repeat bracket
+ struct posit_s posit; /* positions / directions */
+ signed char stem; /* 1 / -1 for stem up / down */
+ signed char combine; /* voice combine */
+ signed char nflags; /* number of note flags when > 0 */
+ char dots; /* number of dots */
+ unsigned char head; /* head type */
+#define H_FULL 0
+#define H_EMPTY 1
+#define H_OVAL 2
+#define H_SQUARE 3
+ signed char multi; /* multi voice in the staff (+1, 0, -1) */
+ signed char nohdi1; /* no head index (for unison) / nb of repeat */
+ signed char nohdi2;
+ signed char doty; /* NOTEREST: y pos of dot when voices overlap
+ * STBRK: forced
+ * FMTCHG REPEAT: infos */
+ short aux; /* auxillary information:
+ * - CLEF: small clef
+ * - KEYSIG: old key signature
+ * - BAR: new bar number
+ * - TUPLET: tuplet format
+ * - NOTE: tremolo number / feathered beam
+ * - FMTCHG (format change): subtype */
+#define PSSEQ 0 /* postscript sequence */
+#define SVGSEQ 1 /* SVG sequence */
+#define REPEAT 2 /* repeat sequence or measure
+ * doty: # measures if > 0
+ * # notes/rests if < 0
+ * nohdi1: # repeat */
+ int color;
+ float x; /* x offset */
+ signed char y; /* y offset of note head */
+ signed char ymn, ymx; /* min, max, note head y offset */
+ signed char mid; // y offset of the staff middle line
+ float xmx; /* max h-pos of a head rel to top
+ * width when STBRK */
+ float xs, ys; /* coord of stem end / bar height */
+ float wl, wr; /* left, right min width */
+ float space; /* natural space before symbol */
+ float shrink; /* minimum space before symbol */
+ float xmax; /* max x offset */
+ struct gch *gch; /* guitar chords / annotations */
+ struct lyrics *ly; /* lyrics */
+
+ char state; /* symbol state in file/tune */
+#define ABC_S_GLOBAL 0 /* global */
+#define ABC_S_HEAD 1 /* in header (after X:) */
+#define ABC_S_TUNE 2 /* in tune (after K:) */
+ unsigned short flags;
+#define ABC_F_ERROR 0x0001 /* error around this symbol */
+#define ABC_F_INVIS 0x0002 /* invisible symbol */
+#define ABC_F_SPACE 0x0004 /* space before a note */
+#define ABC_F_STEMLESS 0x0008 /* note with no stem */
+#define ABC_F_LYRIC_START 0x0010 /* may start a lyric here */
+#define ABC_F_GRACE 0x0020 /* grace note */
+#define ABC_F_GR_END 0x0040 /* end of grace note sequence */
+#define ABC_F_SAPPO 0x0080 /* short appoggiatura */
+#define ABC_F_RBSTART 0x0100 // start of repeat bracket and mark
+#define ABC_F_RBSTOP 0x0200 // end of repeat bracket and mark
+ unsigned short colnum; /* ABC source column number */
+ int linenum; /* ABC source line number */
+ char *fn; /* ABC source file name */
+ char *text; /* main text (INFO, PSCOM),
+ * guitar chord (NOTE, REST, BAR) */
+ union { /* type dependent part */
+ struct key_s { /* K: info */
+ signed char sf; /* sharp (> 0) flats (< 0) */
+ char empty; /* clef alone if 1, 'none' if 2 */
+ char exp; /* exp (1) or mod (0) */
+// char mode; /* mode */
+// /* 0: Ionian, 1: Dorian, 2: Phrygian, 3: Lydian,
+// * 4: Mixolydian, 5: Aeolian, 6: Locrian */
+ char instr; /* specific instrument */
+#define K_HP 1 /* bagpipe */
+#define K_Hp 2
+#define K_DRUM 3 /* percussion */
+ signed char nacc; /* number of explicit accidentals */
+ signed char cue; /* cue voice (scale 0.7) */
+ signed char octave; /* 'octave=' */
+#define NO_OCTAVE 10 /* no 'octave=' */
+ unsigned char microscale; /* microtone denominator - 1 */
+ char clef_delta; /* clef delta */
+ char key_delta; // tonic base
+ char *stafflines;
+ float staffscale;
+ signed char pits[8];
+ unsigned char accs[8];
+ } key;
+ struct { /* L: info */
+ int base_length; /* basic note length */
+ } length;
+ struct meter_s { /* M: info */
+ short wmeasure; /* duration of a measure */
+ unsigned char nmeter; /* number of meter elements */
+ char expdur; /* explicit measure duration */
+#define MAX_MEASURE 16
+ struct {
+ char top[8]; /* top value */
+ char bot[2]; /* bottom value */
+ } meter[MAX_MEASURE];
+ } meter;
+ struct { /* Q: info */
+ char *str1; /* string before */
+ short beats[4]; /* up to 4 beats */
+ short circa; /* "ca. " */
+ short tempo; /* number of beats per mn or */
+ short new_beat; /* old beat */
+ char *str2; /* string after */
+ } tempo;
+ struct { /* V: info */
+ char id[VOICE_ID_SZ]; /* voice ID */
+ char *fname; /* full name */
+ char *nname; /* nick name */
+ float scale; /* != 0 when change */
+ unsigned char voice; /* voice number */
+ signed char octave; /* 'octave=' - same as in K: */
+ char merge; /* merge with previous voice */
+ signed char stem; /* have stems up or down (2 = auto) */
+ signed char gstem; /* have grace stems up or down (2 = auto) */
+ signed char dyn; /* have dynamic marks above or below the staff */
+ signed char lyrics; /* have lyrics above or below the staff */
+ signed char gchord; /* have gchord above or below the staff */
+ signed char cue; /* cue voice (scale 0.7) */
+ char *stafflines;
+ float staffscale;
+ } voice;
+ struct { /* bar, mrest or mrep */
+ int type;
+ char repeat_bar;
+ char len; /* len if mrest or mrep */
+ char dotted;
+ struct decos dc; /* decorations */
+ } bar;
+ struct clef_s { /* clef */
+ char *name; /* PS drawing function */
+ signed char type;
+#define TREBLE 0
+#define ALTO 1
+#define BASS 2
+#define PERC 3
+#define AUTOCLEF 4
+ char line;
+ signed char octave; /* '+8' / '-8' */
+ signed char transpose; /* if '^8' / '_8' */
+ char invis; /* clef 'none' */
+ char check_pitch; /* check if old abc2ps transposition */
+ } clef;
+ struct notes note; /* note, rest */
+ struct { /* user defined accent */
+ unsigned char symbol;
+ unsigned char value;
+ } user;
+ struct {
+ char type; /* 0: end of line
+ * 1: continuation ('\')
+ * 2: line break ('!') */
+ } eoln;
+ struct { /* voice overlay */
+ char type;
+#define V_OVER_V 0 /* & */
+#define V_OVER_S 1 /* (& */
+#define V_OVER_E 2 /* &) */
+ unsigned char voice;
+ } v_over;
+ struct { /* tuplet */
+ char p_plet, q_plet, r_plet;
+ } tuplet;
+ } u;
+};
+
+/* parse definition */
+struct parse {
+ struct SYMBOL *first_sym; /* first symbol */
+ struct SYMBOL *last_sym; /* last symbol */
+ int abc_vers; /* ABC version = (H << 16) + (M << 8) + L */
+ char *deco_tb[DC_NAME_SZ]; /* decoration names */
+ unsigned short micro_tb[MAXMICRO]; /* microtone values [ (n-1) | (d-1) ] */
+ int abc_state; /* parser state */
+};
+extern struct parse parse;
+
+#define FONT_UMAX 10 /* max number of user fonts 0..9 */
+enum e_fonts {
+ ANNOTATIONFONT = FONT_UMAX,
+ COMPOSERFONT,
+ FOOTERFONT,
+ GCHORDFONT,
+ HEADERFONT,
+ HISTORYFONT,
+ INFOFONT,
+ MEASUREFONT,
+ PARTSFONT,
+ REPEATFONT,
+ SUBTITLEFONT,
+ TEMPOFONT,
+ TEXTFONT,
+ TITLEFONT,
+ VOCALFONT,
+ VOICEFONT,
+ WORDSFONT,
+ FONT_DYN /* index of dynamic fonts (gch, an, ly) */
+};
+#define FONT_DYNX 12 /* number of dynamic fonts */
+#define FONT_MAX (FONT_DYN + FONT_DYNX) /* whole number of fonts */
+
+struct FORMAT { /* struct for page layout */
+ float pageheight, pagewidth;
+ float topmargin, botmargin, leftmargin, rightmargin;
+ float topspace, wordsspace, titlespace, subtitlespace, partsspace;
+ float composerspace, musicspace, vocalspace, textspace;
+ float breaklimit, maxshrink, lineskipfac, parskipfac, stemheight;
+ float gutter, indent, infospace, slurheight, notespacingfactor, scale;
+ float staffsep, sysstaffsep, maxstaffsep, maxsysstaffsep, stretchlast;
+ int abc2pscompat, alignbars, aligncomposer, autoclef;
+ int barsperstaff, breakoneoln, bstemdown, cancelkey, capo;
+ int combinevoices, contbarnb, continueall, custos;
+ int dblrepbar, decoerr, dynalign, flatbeams, infoline;
+ int gchordbox, graceslurs, graceword,gracespace, hyphencont;
+ int keywarn, landscape, linewarn;
+ int measurebox, measurefirst, measurenb, micronewps;
+ int oneperpage;
+#ifdef HAVE_PANGO
+ int pango;
+#endif
+ int partsbox, pdfmark;
+ int rbdbstop, rbmax, rbmin;
+ int setdefl, shiftunison, splittune, squarebreve;
+ int staffnonote, straightflags, stretchstaff;
+ int textoption, titlecaps, titleleft, titletrim;
+ int timewarn, transpose, tuplets;
+ char *bgcolor, *dateformat, *header, *footer, *titleformat;
+ char *musicfont;
+ struct FONTSPEC font_tb[FONT_MAX];
+ char ndfont; /* current index of dynamic fonts */
+ unsigned char gcf, anf, vof; /* fonts for guitar chords,
+ * annotations and lyrics */
+ unsigned int fields[2]; /* info fields to print
+ *[0] is 'A'..'Z', [1] is 'a'..'z' */
+ struct posit_s posit;
+};
+
+extern struct FORMAT cfmt; /* current format */
+extern struct FORMAT dfmt; /* global format */
+
+typedef struct SYMBOL *INFO[26]; /* information fields ('A' .. 'Z') */
+extern INFO info;
+
+extern char *outbuf; /* output buffer.. should hold one tune */
+extern int outbufsz; /* size of outbuf */
+extern char *mbf; /* where to PUTx() */
+extern int use_buffer; /* 1 if lines are being accumulated */
+
+extern int outft; /* last font in the output file */
+extern int tunenum; /* number of current tune */
+extern int pagenum; /* current page number */
+extern int pagenum_nr; /* current page (non-resettable) */
+extern int nbar; /* current measure number */
+extern int in_page;
+extern int defl; /* decoration flags */
+#define DEF_NOST 0x01 /* long deco with no start */
+#define DEF_NOEN 0x02 /* long deco with no end */
+#define DEF_STEMUP 0x04 /* stem up (1) or down (0) */
+
+ /* switches modified by flags: */
+extern int quiet; /* quiet mode */
+extern int secure; /* secure mode */
+extern int annotate; /* output source references */
+extern int pagenumbers; /* write page numbers */
+extern int epsf; /* 1: EPSF, 2: SVG, 3: embedded ABC */
+extern int svg; /* 1: SVG, 2: XHTML */
+extern int showerror; /* show the errors */
+extern int pipeformat; /* format for bagpipes */
+
+extern char outfn[FILENAME_MAX]; /* output file name */
+extern char *in_fname; /* current input file name */
+extern time_t mtime; /* last modification time of the input file */
+
+extern int file_initialized; /* for output file */
+extern FILE *fout; /* output file */
+
+#define MAXTBLT 8
+struct tblt_s {
+ char *head; /* PS head function */
+ char *note; /* PS note function */
+ char *bar; /* PS bar function */
+ float wh; /* width of head */
+ float ha; /* height above the staff */
+ float hu; /* height under the staff */
+ short pitch; /* pitch when no associated 'w:' / 0 */
+ char instr[2]; /* instrument pitch */
+};
+extern struct tblt_s *tblts[MAXTBLT];
+
+#define MAXCMDTBLT 4 /* max number of -T in command line */
+struct cmdtblt_s {
+ short index; /* tablature number */
+ short active; /* activate or not */
+ char *vn; /* voice name */
+};
+extern struct cmdtblt_s cmdtblts[MAXCMDTBLT];
+extern int ncmdtblt;
+
+extern int s_argc; /* command line arguments */
+extern char **s_argv;
+
+struct STAFF_S {
+ struct SYMBOL *s_clef; /* clef at start of music line */
+ char empty; /* no symbol on this staff */
+ char *stafflines;
+ float staffscale;
+ short botbar, topbar; /* bottom and top of bar */
+ float y; /* y position */
+ float top[YSTEP], bot[YSTEP]; /* top/bottom y offsets */
+};
+extern struct STAFF_S staff_tb[MAXSTAFF];
+extern int nstaff; /* (0..MAXSTAFF-1) */
+
+struct VOICE_S {
+ char id[VOICE_ID_SZ]; /* voice id */
+ /* generation */
+ struct VOICE_S *next; /* link */
+ struct SYMBOL *sym; /* associated symbols */
+ struct SYMBOL *last_sym; /* last symbol while scanning */
+ struct SYMBOL *lyric_start; /* start of lyrics while scanning */
+ char *nm; /* voice name */
+ char *snm; /* voice subname */
+ char *bar_text; /* bar text at start of staff when bar_start */
+ struct gch *bar_gch; /* bar text */
+ struct SYMBOL *tie; /* note with ties of previous line */
+ struct SYMBOL *rtie; /* note with ties before 1st repeat bar */
+ struct tblt_s *tblts[2]; /* tablatures */
+ float scale; /* scale */
+ int time; /* current time (parsing) */
+ struct SYMBOL *s_clef; /* clef at end of music line */
+ struct key_s key; /* current key signature */
+ struct meter_s meter; /* current time signature */
+ struct key_s ckey; /* key signature while parsing */
+ struct key_s okey; /* original key signature (parsing) */
+ unsigned hy_st; /* lyrics hyphens at start of line (bit array) */
+ unsigned ignore:1; /* ignore this voice (%%staves) */
+ unsigned second:1; /* secondary voice in a brace/parenthesis */
+ unsigned floating:1; /* floating voice in a brace system */
+ unsigned bar_repeat:1; /* bar at start of staff is a repeat bar */
+ unsigned norepbra:1; /* don't display the repeat brackets */
+ unsigned have_ly:1; /* some lyrics in this voice */
+ unsigned new_name:1; /* redisplay the voice name */
+ unsigned space:1; /* have a space before the next note (parsing) */
+ unsigned perc:1; /* percussion */
+ unsigned auto_len:1; /* auto L: (parsing) */
+ short wmeasure; /* measure duration (parsing) */
+ short transpose; /* transposition (parsing) */
+ short bar_start; /* bar type at start of staff / 0 */
+ struct posit_s posit; /* positions / directions */
+ signed char octave; /* octave (parsing) */
+ signed char ottava; /* !8va(! ... (parsing) */
+ signed char clone; /* duplicate from this voice number */
+ signed char over; /* overlay of this voice number */
+ unsigned char staff; /* staff (0..n-1) */
+ unsigned char cstaff; /* staff (parsing) */
+ unsigned char slur_st; /* slurs at start of staff */
+ signed char combine; /* voice combine */
+ int color;
+ char *stafflines;
+ float staffscale;
+ /* parsing */
+ struct SYMBOL *last_note; /* last note or rest */
+ char *map_name;
+ int ulen; /* unit note length */
+ unsigned char microscale; /* microtone scale */
+ unsigned char mvoice; /* main voice when voice overlay */
+};
+extern struct VOICE_S *curvoice; /* current voice while parsing */
+extern struct VOICE_S voice_tb[MAXVOICE]; /* voice table */
+extern struct VOICE_S *first_voice; /* first_voice */
+
+extern struct SYMBOL *tsfirst; /* first symbol in the time linked list */
+extern struct SYMBOL *tsnext; /* next line when cut */
+extern float realwidth; /* real staff width while generating */
+
+#define NFLAGS_SZ 10 /* size of note flags tables */
+#define C_XFLAGS 5 /* index of crotchet in flags tables */
+extern float space_tb[NFLAGS_SZ]; /* note spacing */
+extern float hw_tb[]; // width of note heads
+
+struct SYSTEM { /* staff system */
+ struct SYSTEM *next;
+ short top_voice; /* first voice in the staff system */
+ short nstaff;
+ struct {
+ short flags;
+#define OPEN_BRACE 0x01
+#define CLOSE_BRACE 0x02
+#define OPEN_BRACKET 0x04
+#define CLOSE_BRACKET 0x08
+#define OPEN_PARENTH 0x10
+#define CLOSE_PARENTH 0x20
+#define STOP_BAR 0x40
+#define FL_VOICE 0x80
+#define OPEN_BRACE2 0x0100
+#define CLOSE_BRACE2 0x0200
+#define OPEN_BRACKET2 0x0400
+#define CLOSE_BRACKET2 0x0800
+#define MASTER_VOICE 0x1000
+ char empty;
+ char *stafflines;
+ float staffscale;
+// struct clef_s clef;
+ float sep, maxsep;
+ } staff[MAXSTAFF];
+ struct {
+ signed char range;
+ unsigned char staff;
+ char second;
+ char dum;
+ float sep, maxsep;
+// struct clef_s clef;
+ } voice[MAXVOICE];
+};
+extern struct SYSTEM *cursys; /* current staff system */
+
+/* -- external routines -- */
+/* abcm2ps.c */
+void include_file(unsigned char *fn);
+void clrarena(int level);
+int lvlarena(int level);
+void *getarena(int len);
+void strext(char *fid, char *ext);
+/* abcparse.c */
+void abc_parse(char *p, char *fname, int linenum);
+void abc_eof(void);
+char *get_str(char *d,
+ char *s,
+ int maxlen);
+char *parse_acc_pit(char *p,
+ int *pit,
+ int *acc);
+/* buffer.c */
+void a2b(char *fmt, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 1, 2)))
+#endif
+ ;
+void block_put(void);
+void buffer_eob(int eot);
+void marg_init(void);
+void bskip(float h);
+void check_buffer(void);
+void init_outbuf(int kbsz);
+void close_output_file(void);
+void close_page(void);
+float get_bposy(void);
+void open_fout(void);
+void write_buffer(void);
+extern int (*output)(FILE *out, const char *fmt, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 2, 3)))
+#endif
+ ;
+void write_eps(void);
+/* deco.c */
+void deco_add(char *text);
+void deco_cnv(struct decos *dc, struct SYMBOL *s, struct SYMBOL *prev);
+void deco_update(struct SYMBOL *s, float dx);
+float deco_width(struct SYMBOL *s);
+void draw_all_deco(void);
+//int draw_deco_head(int deco, float x, float y, int stem);
+void draw_deco_near(void);
+void draw_deco_note(void);
+void draw_deco_staff(void);
+float draw_partempo(int staff, float top);
+void draw_measnb(void);
+void init_deco(void);
+void reset_deco(void);
+void set_defl(int new_defl);
+float tempo_width(struct SYMBOL *s);
+void write_tempo(struct SYMBOL *s,
+ int beat,
+ float sc);
+float y_get(int staff,
+ int up,
+ float x,
+ float w);
+void y_set(int staff,
+ int up,
+ float x,
+ float w,
+ float y);
+/* draw.c */
+void draw_sym_near(void);
+void draw_all_symb(void);
+float draw_systems(float indent);
+void output_ps(struct SYMBOL *s, int color);
+struct SYMBOL *prev_scut(struct SYMBOL *s);
+void putf(float f);
+void putx(float x);
+void puty(float y);
+void putxy(float x, float y);
+void set_scale(struct SYMBOL *s);
+void set_sscale(int staff);
+void set_color(int color);
+/* format.c */
+void define_fonts(void);
+int get_textopt(char *p);
+int get_font_encoding(int ft);
+int get_bool(char *p);
+void interpret_fmt_line(char *w, char *p, int lock);
+void lock_fmt(void *fmt);
+void make_font_list(void);
+FILE *open_file(char *fn,
+ char *ext,
+ char *rfn);
+void print_format(void);
+void set_font(int ft);
+void set_format(void);
+void set_voice_param(struct VOICE_S *p_voice, int state, char *w, char *p);
+struct tblt_s *tblt_parse(char *p);
+/* front.c */
+#define FE_ABC 0
+#define FE_FMT 1
+#define FE_PS 2
+void frontend(unsigned char *s,
+ int ftype,
+ char *fname,
+ int linenum);
+/* glyph.c */
+char *glyph_out(char *p);
+void glyph_add(char *p);
+/* music.c */
+void output_music(void);
+void reset_gen(void);
+void unlksym(struct SYMBOL *s);
+/* parse.c */
+extern float multicol_start;
+void do_tune(void);
+void identify_note(struct SYMBOL *s,
+ int len,
+ int *p_head,
+ int *p_dots,
+ int *p_flags);
+void sort_pitch(struct SYMBOL *s);
+struct SYMBOL *sym_add(struct VOICE_S *p_voice,
+ int type);
+/* subs.c */
+void bug(char *msg, int fatal);
+void error(int sev, struct SYMBOL *s, char *fmt, ...);
+float scan_u(char *str, int type);
+float cwid(unsigned char c);
+void get_str_font(int *cft, int *dft);
+void set_str_font(int cft, int dft);
+#ifdef HAVE_PANGO
+void pg_init(void);
+void pg_reset_font(void);
+#endif
+void put_history(void);
+void put_words(struct SYMBOL *words);
+void str_font(int ft);
+#define A_LEFT 0
+#define A_CENTER 1
+#define A_RIGHT 2
+#define A_LYRIC 3
+#define A_GCHORD 4
+#define A_ANNOT 5
+#define A_GCHEXP 6
+void str_out(char *p, int action);
+void put_str(char *str, int action);
+float tex_str(char *s);
+extern char tex_buf[]; /* result of tex_str() */
+#define TEX_BUF_SZ 512
+char *trim_title(char *p, struct SYMBOL *title);
+void user_ps_add(char *s, char use);
+void user_ps_write(void);
+void write_title(struct SYMBOL *s);
+void write_heading(void);
+void write_user_ps(void);
+void write_text(char *cmd, char *s, int job);
+/* svg.c */
+void define_svg_symbols(char *title, int num, float w, float h);
+void svg_def_id(char *id, int idsz);
+void svg_font_switch(void);
+int svg_output(FILE *out, const char *fmt, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 2, 3)))
+#endif
+ ;
+void svg_write(char *buf, int len);
+void svg_close();
+/* syms.c */
+void define_font(char *name, int num, int enc);
+void define_symbols(void);
diff -Nru abcm2ps-7.8.9/abcm2ps.rst abcm2ps-8.14.2/abcm2ps.rst
--- abcm2ps-7.8.9/abcm2ps.rst 1970-01-01 00:00:00.000000000 +0000
+++ abcm2ps-8.14.2/abcm2ps.rst 2018-12-18 15:18:26.000000000 +0000
@@ -0,0 +1,662 @@
+..
+ Process this file with rst2man from python-docutils
+ to generate a nroff manual page
+
+=======
+abcm2ps
+=======
+
+--------------------------------------------------
+translate ABC music notation to PostScript or SVG
+--------------------------------------------------
+
+SYNOPSIS
+========
+
+ ``abcm2ps`` [global_options] ABC_file [file_options] ...
+
+DESCRIPTION
+===========
+
+``abcm2ps`` translates tunes written in
+the ABC music notation format to customary sheet music scores in
+PostScript or SVG. It is based on ``abc2ps`` 1.2.5 and was
+developed mainly to print Baroque organ scores that have
+independent voices played on multiple keyboards and a
+pedal-board. The program has since been extended to support
+various other notation conventions in use for sheet music.
+
+Options given immediately after the command name apply to
+the run as a whole; options given after an ABC file name apply
+to that file.
+
+Formatting parameters can also be set in "format files" and
+in the ABC files themselves.
+
+OPTIONS
+=======
+
+The list of the command line options may be known running::
+
+ abcm2ps -h
+
+The options may be grouped when they have no argument, but the
+last one (ex: ``-lnGI20``).
+
+The options may be disabled when starting with '+' or ending with '-'
+(ex: ``+MT1`` is the same as ``-MT1-``).
+
+The general output format is the last found in the command line.
+It may be:
+
+-E for Encapsulated PostScript, one file per tune
+
+-g for SVG, one file per tune
+
+-v for SVG, one file per page
+
+-X for XHTML+SVG
+
+-z for (X)HTML+SVG with (X)HTML+ABC input
+
+(see below for more information)
+
+List of the options
+-------------------
+
+\-
+ Read the abc file from stdin.
+
+\--
+ Set the parameter to .
+
+ This has the same effect as a format parameter
+ directly in the source file.
+
+-a
+ Maximal horizontal compression when staff breaks are
+ chosen automatically. Must be a float between 0 and 1.
+
+ This correspond to the ``%%maxshrink``
+ formatting parameter (default: 0.65).
+
+-A
+ This option inserts reference elements in the PostScript
+ or SVG output.
+
+-B , +B
+ Try to typeset bars on each staff line.
+
+ This corresponds to the ``%%barsperstaff`` formatting parameter.
+
+-b
+ Start measure numbering at .
+
+ This corresponds to the ``%%measurefirst`` formatting parameter.
+
+-c, +c
+ The continuation symbol is implicitly appended to each
+ music line. This amounts to automatic line breaking.
+
+ This corresponds to the ``%%continueall`` formatting parameter.
+
+-D
+ Search the format files in the directory .
+
+-d
+ Set the vertical interstaff space to .
+
+ This corresponds to the ``%%staffsep`` formatting parameter
+ (default: 46pt).
+
+-E
+ Produce EPS output instead of simple PS.
+
+ In this mode, each tune goes to a different file which
+ name is "nnn.eps" or ".eps" (see option '-O')
+
+ - 'nnn' is a sequence number incremented at each tune
+
+ Output to stdout is forbidden.
+
+ EPS files are normally embedded into Postscript documents,
+ but they may be a way to generate graphical images. For
+ example, using GhostScript::
+
+ abcm2ps voices -Ee7
+ gs -sDEVICE=pngmono -r80 -g590x174 \
+ -dBATCH -dNOPAUSE \
+ -sOutputFile=quitolis.png Out001.eps
+
+ \(the values for -g are the values of the bounding box in
+ the .eps, multiplied by (80 / 72), where 80 is the value
+ for -r, and 72 is the default resolution)
+
+-e [ ] [ ]
+ Select which tunes from an ABC file to print.
+
+ is either a comma-separated list of tune
+ numbers (as per the ``X:`` header), or a regular expression
+ which will be matched against the tune headers as a whole.
+ The ``-e`` option must occur after an ABC file
+ name and applies to that file.
+
+ Ranges of tune numbers may be specified like ``-``;
+ may be omitted which means
+ "all remaining tunes until the end of file". Note that
+ filtering may cause problems, e.g., with global (non-tune)
+ definitions in the ABC file.
+
+ This corresponds to the ``%%select`` formatting parameter.
+
+-F , +F
+ Read the format (or PostScript) file .
+
+ When omitted, the default type of a format file is '.fmt'.
+
+ In the form '+F', the default format file ('default.fmt') is not
+ read.
+
+-f
+ Enable flat beams (useful for bagpipe tunes).
+
+ This corresponds to the ``%%flatbeams`` formatting parameter.
+
+-G, +G
+ Omit slurs on grace notes.
+
+ This corresponds to the ``%%graceslurs`` formatting parameter.
+
+-g
+ Produce SVG output instead of EPS.
+
+ In this mode each tune goes to a different file which name
+ is 'Outnnn.svg' (see option '-O').
+
+ If the output is stdout (option '-O-'), all the SVG images
+ are output without XML header.
+
+-H
+ Display the current format values.
+
+-h
+ Quick help, equivalent to "abcm2ps" without any arguments.
+
+ This also shows the default settings for some parameters.
+
+-I
+ Indent the first line of the tune by (default: 0).
+
+ This corresponds to the ``%%indent`` formatting parameter.
+
+-i, +i
+ Insert a red cercle around the errors in the PostScript output.
+
+-j [b], +j
+ Output a measure number every measures.
+
+ If is 0, the measure number appears at the left of each staff.
+ The trailing ``b`` causes a box to be drawn
+ around each measure number (default: no measure numbering).
+
+ This corresponds to the ``%%measurenb`` formatting parameter.
+
+-k
+ Set the size of the PostScript output buffer in Kibytes.
+
+ Setting this value to a higher value permits the
+ generation of big tunes with -E or -g. The default value is 64.
+
+-l, +l
+ Generate landscape output.
+
+ This corresponds to the ``%%landscape`` formatting parameter.
+
+-M, +M
+ Suppress lyrics.
+
+ See the ``%%writefields w`` formatting parameter.
+
+-m
+ Set the left margin to (default: 1.8cm).
+
+ This corresponds to the ``%%leftmargin`` formatting parameter.
+
+-N , +N
+ Number the pages.
+
+ indicates the mode:
+
+ 0
+ no page numbers
+ 1
+ at top left
+ 2
+ at top right
+ 3
+ at top left on even pages, top right on odd pages
+ 4
+ at top right on even pages, top left on odd pages
+
+ For compatibility with previous versions, '+N' is the same as
+ '-N0', and '-N' is the same as '-N2'.
+
+ If a header is defined ("%%header"), this option is ignored.
+
+-n, +n
+ Include notes and history from ABC tune ``N:`` fields.
+
+ See the ``%%writehistory N`` formatting parameter.
+
+-O [ ] [ ], +O
+ Define the output file directory and/or name.
+
+ The directory must end with the directory separator
+ ('/' for unix/windows, '\\' for mac).
+
+ By default, the output file goes to the current directory
+ with the name:
+
+ 'Out.ps' for PS,
+
+ 'Outnnn.eps' for EPS (see option '-E'),
+
+ 'Outnnn.svg' for SVG (see options '-g' and '-v') or
+
+ 'Out.xhtml' for XHTML+SVG (see options '-X' and '-z').
+
+ 'nnn' is a sequence number.
+
+ When is present, it is the name of the file, or it
+ replaces "Out" in the file name.
+
+ If is '=', it is replaced by the name of the ABC
+ source file (not for '-z').
+
+ If is '-', the result is output to stdout (not for EPS).
+ '+O' resets the output file directory and name to their defaults.
+
+-p
+ Bagpipe format.
+
+ When present, format output for bagpipe regardless of key.
+
+-q
+ Quiet mode.
+
+ When present, only the errors are shown.
+
+-s
+ Set the page scale factor to . Note that the header
+ and footer are not scaled (default: 0.75).
+
+ This corresponds to the ``%%scale`` formatting parameter.
+
+-S
+ Secure mode.
+
+ When present, file inclusion (%%format and %%EPS) and PostScript
+ injection (%%beginps and %%postscript) are disabled.
+
+-T [ ], +T [ [ ] ]
+ Activate or deactivate tablature drawing.
+
+ - is the tablature number as defined in ``%%tablature``.
+ There may be only 8 different tablatures.
+
+ - is the voice name, full name or subname as found in V:.
+ When absent, apply to all voices.
+
+ Up to 4 such commands may be defined.
+
+ Ex: '-T1flute +T2'
+
+-V
+ Show the version number.
+
+-v
+ Produce SVG output instead of simple PS.
+
+ In this mode each page goes to a different file which name
+ is 'Outnnn.svg' (see option '-O').
+
+-w
+ Adjust the right margin such that the staff width
+ is (default: none).
+
+ This corresponds to the ``%%staffwidth`` formatting parameter.
+
+-X
+ Produce XML+SVG output instead of simple PS.
+
+ The default file name is 'Out.xhtml' (see option '-O').
+
+-x, +x
+ Include the ``X:`` tune number in the title.
+
+ This corresponds to the ``%%writefields`` formatting parameter.
+
+-z
+ Produce SVG images from ABC embedded in markup language files
+ (HTML, XHTML..).
+
+ The source file is copied to the output file and the ABC sequences
+ are converted to SVG images.
+ The ABC sequences start by either ``%abc..`` or ``X:..``
+ and stop on the first markup tag (``<..``).
+
+ The generation creates one image per block, i.e. a music line
+ or a text block. For a same rendering as the other SVG generation
+ (-g, -v or -X), don't forget to set the line space to null, for
+ example enclosing the ABC sequences by::
+
+ ..
+
+ There can be only one output file.
+
+ Note that the default output file is 'Out.xhtml', so, don't
+ forget to change the file type if you generate HTML (.html)
+ or XML (.xml) files.
+
+ See "sample8.html" for a source example.
+
+-0, +0
+ Split tunes across page breaks if necessary.
+
+ This corresponds to the ``%%splittune`` formatting parameter.
+
+-1, +1
+ Output one tune per page.
+
+ This corresponds to the ``%%oneperpage`` formatting parameter.
+
+ADDITIONAL FEATURES
+===================
+
+Clefs
+ Clefs can be given in ``K:`` and ``V:`` headers.
+ The full syntax is::
+
+ clef=[+8|-8]
+
+ "clef=" can be omitted when the is a clef name.
+
+ denotes the clef type. It may be:
+
+ - A note pitch (``G``, ``C``, or ``F``)
+
+ The pitch indicates which clef is meant:
+ ``G`` is the treble clef,
+ ``C`` the alto clef and
+ ``F`` the bass clef.
+ It also gives the name of the note that appears
+ on the clef's line.
+
+ - A clef name
+
+ The available clef names are
+ ``treble`` (clef gives the pitch for ``G``),
+ ``alto`` or ``tenor`` (``C``), and
+ ``bass`` (``F``).
+
+ - ``perc`` or ``P``
+
+ In percussion mode, accidentals change the glyphs used for
+ note heads. By default, sharp notes are drawn as "x" and
+ flat notes as circled "x".
+ This may be changed by redefining the PostScript functions
+ ``pshhd`` and ``pflhd``.
+
+ - ``none``
+
+ No clef will be displayed.
+
+ The gives the number of
+ the line within the staff that the base clef will be written
+ on. The default values are 2 for the treble clef, 3 for the
+ alto clef, and 4 for the tenor and bass clefs.
+
+ The "+8" and "-8"
+ options draw an 8 above or below the staff, respectively.
+
+ When no clef is specified, clef changes
+ between "bass"
+ and "treble" will be inserted
+ automatically.
+
+Multi-voice typesetting
+ Multiple voices may be defined within the header or the
+ tune using::
+
+ V: ...
+
+ where is a word consisting of letters and digits only
+ (like "violin1"). In the tune body, the
+ following notes refer to this voice until
+ another "V:" is encountered.
+
+ A can be one of:
+
+ * "clef="...
+
+ See above
+
+ * "name=" or "nm="
+
+ The will be
+ displayed at the beginning of the first staff. It can
+ contain "\\n" sequences
+ which will force line breaks. If it contains
+ whitespace it must be double-quoted.
+
+ * "subname=" or "snm="
+
+ The will be displayed at the beginning of all staves
+ except for the first. It can
+ contain "\\n" sequences
+ which will force line breaks. If it contains
+ whitespace it must be double-quoted.
+
+ * "merge"
+
+ The voice goes on the same staff as the previous voice.
+
+ * "up" or "down"
+
+ Forces the direction of the stems for the voice.
+
+ * "dyn=up" or "dyn=down" or "dyn=auto"
+
+ Forces positioning of dynamic marks (above or
+ below the staff) or reverts to automatic positioning
+ (the default).
+
+ * "gstem=up" or "gstem=down" or "gstem=auto"
+
+ Forces the direction of the stems of grace
+ notes (always up or always down) or reverts to
+ automatic positioning (the default).
+
+ * "stem=auto"
+
+ Reverts to automatic positioning of note stems
+ (up or down) (the default).
+
+ * "lyrics=up" or "lyrics=down" or "lyrics=auto"
+
+ Places lyrics above or below the staff or
+ reverts to automatic positioning (the default)
+
+ * "gchord=up" or "gchord=down"
+
+ Places guitar chords above (the default) or below the staff.
+
+ * "stafflines="
+
+ Sets the number of lines on the staff in question. (default: 5)
+
+ * "staffscale="
+
+ Sets the scale of the associated staff up to 3. (default: 1)
+
+ All other definitions are ignored.
+
+Definition of the staff system
+ By default, each voice goes on its own
+ staff. The ``%%staves ``
+ pseudo-comment can be used to control staff
+ assignment. The
+ consists of voice names (from ``V:``) and pairs of
+ parentheses, braces or brackets.
+
+ - When a voice name is not within a pair of
+ special characters, it goes on a separate staff.
+
+ - For voice names enclosed in brackets, a bracket
+ is displayed at the beginning of each line that joins
+ the staves of the voices in question.
+
+ - For voice names enclosed in braces, all the
+ voices go on two staves (keyboard score). There can be
+ at most four voices between a single pair of braces.
+
+ - For voice names enclosed in parentheses, all the
+ voices appear on a single staff.
+
+ The ``|`` character prevents measure bars from
+ being drawn between two staves.
+ If ``%%staves`` occurs in a tune, all the
+ voices not mentioned will not be output at all.
+
+ The ``%%score`` directive occurs in the ABC
+ draft 2.0 standard and is similar to
+ the ``%%staves`` specification described
+ above. The rules are:
+
+ - Voice names within parentheses form a "voice
+ group" and go on a single staff. A voice name that is
+ not within parentheses forms its own voice group and
+ goes on a staff by itself.
+
+ - Voice groups within braces form a "voice block"
+ and are preceded by a big brace in the output. This is
+ especially useful for keyboard music.
+
+ - Voice groups or voice blocks within brackets
+ form a "voice block" and will be preceded by a big
+ bracket in the output.
+
+ - If a ``|`` character occurs between two
+ voice groups or voice blocks, the bar lines in all of
+ the associated staves will be continuous.
+
+ - A single voice surrounded by two voice groups
+ can be preceded by an asterisk to make it into a
+ "floating" voice. This means that, for each note of the
+ voice, a separate decision is made whether it is printed
+ on the preceding or the following voice group's staff.
+
+ - Voices that appear in the tune body but not in
+ the ``%%score`` directive will not be output at
+ all. If there is no ``%%score`` directive, each
+ voice will be output on its own staff.
+
+ - A ``%%score`` directive inside a tune
+ resets the mechanism so voices can be removed or added.
+
+Voice overlay
+ You can add notes to a staff without introducing a
+ complete extra voice by using the ampersand
+ (``&``). A single measure can be split into two voices like::
+
+ |F2A2Bc&F2c2bc|
+
+ The ``(&...&...&)`` construction allows splitting multiple
+ measures::
+
+ |!f!(&GG``.
+
+SEE ALSO
+========
+
+A brief introduction referencing further documentation is
+installed in /abcm2ps/README.md.
+
+The ABC music notation is at http://abcnotation.com/.
+
+Especially, you may find a discussion of differences with the
+ABC standard at http://moinejf.free.fr/abcm2ps-doc/features.xhtml
+and a list of formatting options at http://moinejf.free.fr/abcm2ps-doc/.
+
+AUTHOR
+======
+
+``abcm2ps`` was written by Jean-François Moine
+starting from ``abc2ps`` by Michael Methfessel.
+
+Parts of this manual have been written by Anselm Lingnau
+ for the ``Debian`` system.
+
+Permission is granted to copy, distribute and/or modify this
+document as long as its origin is not misrepresented.
diff -Nru abcm2ps-7.8.9/abcparse.c abcm2ps-8.14.2/abcparse.c
--- abcm2ps-7.8.9/abcparse.c 2014-07-12 17:03:05.000000000 +0000
+++ abcm2ps-8.14.2/abcparse.c 2018-12-18 15:18:26.000000000 +0000
@@ -1,22 +1,13 @@
/*
* Generic ABC parser.
*
- * Copyright (C) 1998-2014 Jean-François Moine
+ * Copyright (C) 1998-2018 Jean-François Moine
* Adapted from abc2ps, Copyright (C) 1996, 1997 Michael Methfessel
*
* This program 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 2 of the License, or
* (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*/
#include "config.h"
@@ -25,71 +16,57 @@
#include
#include
-#include "abcparse.h"
-
-/* interface */
-static void *(*alloc_f)(int size);
-static void (*free_f)(void *);
-static void (*level_f)(int level);
-static int client_sz;
-static int keep_comment;
+#include "abcm2ps.h"
/* global values */
-char *deco_tb[128]; /* decoration names */
int severity; /* error severity */
-static int abc_vers; /* abc version */
-static short abc_state; /* parse state */
-static short ulen; /* unit note length set by M: or L: */
+static int ulen; /* unit note length set by M: or L: */
static short meter; /* upper value of time sig for n-plets */
static unsigned char microscale; /* current microtone scale */
static signed char vover; /* voice overlay (1: single bar, -1: multi-bar */
static char lyric_started; /* lyric started */
static char *gchord; /* guitar chord */
-static struct deco dc; /* decorations */
-static struct abcsym *deco_start; /* 1st note of the line for d: / s: */
-static struct abcsym *deco_cont; /* current symbol when d: / s: continuation */
-static unsigned short *p_micro; /* ptr to the microtone table of the tune */
-
-#define VOICE_NAME_SZ 64 /* max size of a voice name */
+static struct decos dc; /* decorations */
+static struct SYMBOL *deco_start; /* 1st note of the line for d: / s: */
+static struct SYMBOL *deco_cont; /* current symbol when d: / s: continuation */
+
+static int g_abc_vers, g_ulen, g_microscale;
+static char g_char_tb[128];
+static char *g_deco_tb[128]; /* global decoration names */
+static unsigned short g_micro_tb[MAXMICRO]; /* global microtone values */
-static char *file; /* remaining abc file */
+static char *abc_fn; /* current source file name */
static int linenum; /* current source line number */
static int colnum; /* current source column number */
static char *abc_line; /* line being parsed */
-static struct abcsym *last_sym; /* last symbol for errors */
+static struct SYMBOL *last_sym; /* last symbol for errors */
static short nvoice; /* number of voices (0..n-1) */
-static struct { /* voice table and current pointer */
- char id[VOICE_ID_SZ]; /* voice ID */
- struct abcsym *last_note; /* last note or rest */
- short ulen; /* unit note length */
- unsigned char microscale; /* microtone scale */
- unsigned char mvoice; /* main voice when voice overlay */
-} voice_tb[MAXVOICE], *curvoice;
+struct VOICE_S *curvoice; /* current voice while parsing */
+
+struct parse parse;
/* char table for note line parsing */
#define CHAR_BAD 0
#define CHAR_IGN 1
#define CHAR_NOTE 2
-#define CHAR_REST 3
-#define CHAR_ACC 4
-#define CHAR_GR_ST 5
-#define CHAR_DECO 6
-#define CHAR_GCHORD 7
-#define CHAR_BSLASH 8
-#define CHAR_OBRA 9
-#define CHAR_BAR 10
-#define CHAR_OPAR 11
-#define CHAR_VOV 12
-#define CHAR_SPAC 13
-#define CHAR_MINUS 14
-#define CHAR_CPAR 15
-#define CHAR_BRHY 16
-#define CHAR_DECOS 17
-#define CHAR_SLASH 18
-#define CHAR_GR_EN 19
-#define CHAR_LINEBREAK 20
+#define CHAR_GR_ST 3
+#define CHAR_DECO 4
+#define CHAR_GCHORD 5
+#define CHAR_BSLASH 6
+#define CHAR_OBRA 7
+#define CHAR_BAR 8
+#define CHAR_OPAR 9
+#define CHAR_VOV 10
+#define CHAR_SPAC 11
+#define CHAR_MINUS 12
+#define CHAR_CPAR 13
+#define CHAR_BRHY 14
+#define CHAR_DECOS 15
+#define CHAR_SLASH 16
+#define CHAR_GR_EN 17
+#define CHAR_LINEBREAK 18
static char char_tb[256] = {
0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 07 */
0, CHAR_SPAC, CHAR_LINEBREAK, 0, 0, 0, 0, 0, /* 08 - 0f */
@@ -102,22 +79,22 @@
CHAR_BAD, CHAR_BAD, CHAR_BAD, CHAR_BAD, /* 0 1 2 3 */
CHAR_BAD, CHAR_BAD, CHAR_BAD, CHAR_BAD, /* 4 5 6 7 */
CHAR_BAD, CHAR_BAD, CHAR_BAR, CHAR_BAD, /* 8 9 : ; */
- CHAR_BRHY, CHAR_ACC, CHAR_BRHY, CHAR_BAD, /* < = > ? */
+ CHAR_BRHY, CHAR_NOTE, CHAR_BRHY, CHAR_BAD, /* < = > ? */
CHAR_BAD, CHAR_NOTE, CHAR_NOTE, CHAR_NOTE, /* @ A B C */
CHAR_NOTE, CHAR_NOTE, CHAR_NOTE, CHAR_NOTE, /* D E F G */
CHAR_DECO, CHAR_DECO, CHAR_DECO, CHAR_DECO, /* H I J K */
CHAR_DECO, CHAR_DECO, CHAR_DECO, CHAR_DECO, /* L M N O */
CHAR_DECO, CHAR_DECO, CHAR_DECO, CHAR_DECO, /* P Q R S */
CHAR_DECO, CHAR_DECO, CHAR_DECO, CHAR_DECO, /* T U V W */
- CHAR_REST, CHAR_DECO, CHAR_REST, CHAR_OBRA, /* X Y Z [ */
- CHAR_BSLASH, CHAR_BAR, CHAR_ACC, CHAR_ACC, /* \ ] ^ _ */
+ CHAR_NOTE, CHAR_DECO, CHAR_NOTE, CHAR_OBRA, /* X Y Z [ */
+ CHAR_BSLASH, CHAR_BAR, CHAR_NOTE, CHAR_NOTE, /* \ ] ^ _ */
CHAR_IGN, CHAR_NOTE, CHAR_NOTE, CHAR_NOTE, /* ` a b c */
CHAR_NOTE, CHAR_NOTE, CHAR_NOTE, CHAR_NOTE, /* d e f g */
CHAR_DECO, CHAR_DECO, CHAR_DECO, CHAR_DECO, /* h i j k */
CHAR_DECO, CHAR_DECO, CHAR_DECO, CHAR_DECO, /* l m n o */
CHAR_DECO, CHAR_DECO, CHAR_DECO, CHAR_DECO, /* p q r s */
CHAR_DECO, CHAR_DECO, CHAR_DECO, CHAR_DECO, /* t u v w */
- CHAR_REST, CHAR_REST, CHAR_REST, CHAR_GR_ST, /* x y z { */
+ CHAR_NOTE, CHAR_NOTE, CHAR_NOTE, CHAR_GR_ST, /* x y z { */
CHAR_BAR, CHAR_GR_EN, CHAR_DECO, CHAR_BAD, /* | } ~ (del) */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9f */
@@ -131,22 +108,10 @@
static const char all_notes[] = "CDEFGABcdefgab";
-static char *get_line(void);
-static char *parse_len(char *p,
- int *p_len);
-static char *parse_basic_note(char *p,
- int *pitch,
- int *length,
- int *accidental,
- int *stemless);
-static int parse_info(struct abctune *t,
- char *p,
- char *comment);
+static int parse_info(char *p);
static char *parse_gchord(char *p);
-static int parse_line(struct abctune *t,
- char *p);
-static char *parse_note(struct abctune *t,
- char *p,
+static int parse_line(char *p);
+static char *parse_note(char *p,
int flags);
static void syntax(char *msg, char *q);
static void vover_new(void);
@@ -155,305 +120,98 @@
static void print_error(char *s, int col)
{
if (col >= 0)
- fprintf(stderr, "Error in line %d.%d: %s\n", linenum, col, s);
+ fprintf(stderr, "%s:%d:%d: error: %s\n", abc_fn, linenum, col, s);
else
- fprintf(stderr, "Error in line %d: %s\n", linenum, s);
-}
-
-/* -- delete an ABC symbol -- */
-void abc_delete(struct abcsym *as)
-{
- switch (as->type) {
- case ABC_T_INFO:
- switch (as->text[0]) {
- case 'Q':
- if (as->u.tempo.str1)
- free_f(as->u.tempo.str1);
- if (as->u.tempo.value)
- free_f(as->u.tempo.value);
- if (as->u.tempo.str2)
- free_f(as->u.tempo.str2);
- break;
- case 'V':
- if (as->u.voice.fname)
- free_f(as->u.voice.fname);
- if (as->u.voice.nname)
- free_f(as->u.voice.nname);
- break;
- }
- break;
- }
- if (as->text)
- free_f(as->text);
- if (as->comment)
- free_f(as->comment);
-
- if (as->prev)
- as->prev->next = as->next;
- if (as->next)
- as->next->prev = as->prev;
- if (as->tune->first_sym == as)
- as->tune->first_sym = as->next;
- if (as->tune->last_sym == as)
- as->tune->last_sym = as->prev;
- free_f(as);
-}
-
-/* -- free the memory areas of all tunes -- */
-void abc_free(struct abctune *t)
-{
- struct abctune *tn;
- struct abcsym *s, *sn;
-
- if (!free_f)
- return;
- for (;;) {
- if (!t)
- break;
- s = t->first_sym;
-
- /* free the associated symbols */
- for (;;) {
- sn = s->next;
- abc_delete(s);
- if ((s = sn) == NULL)
- break;
- }
-
- /* free the tune */
- tn = t->next;
- free_f(t);
- t = tn;
- }
+ fprintf(stderr, "%s:%d: error: %s\n", abc_fn, linenum, s);
}
-/* -- initialize the parser -- */
-void abc_init(void *alloc_f_api(int size),
- void free_f_api(void *ptr),
- void level_f_api(int level),
- int client_sz_api,
- int keep_comment_api)
+/* -- new symbol -- */
+static struct SYMBOL *abc_new(int type, char *text)
{
- if (alloc_f) {
- fprintf(stderr, "abc_init already initialized\n");
- return;
- }
- alloc_f = alloc_f_api;
- free_f = free_f_api;
- level_f = level_f_api;
- client_sz = client_sz_api;
- keep_comment = keep_comment_api;
-}
-
-/* -- insert an ABC description -- */
-void abc_insert(char *file_api,
- struct abcsym *s)
-{
- struct abctune *t;
- char *p;
-
- /* initialize */
- file = file_api;
- if (level_f)
- level_f(abc_state != ABC_S_GLOBAL);
- abc_state = ABC_S_TUNE;
- linenum = 0;
- t = s->tune;
- t->last_sym = s;
+ struct SYMBOL *s;
- /* scan till end of description */
- for (;;) {
- if ((p = get_line()) == NULL)
- break; /* done */
- if (*p == '\0')
- break; /* blank line --> done */
-/*fixme-insert: don't accept X:*/
- /* parse the music line */
- if (parse_line(t, p))
- break;
- }
-}
-
-/* -- new symbol -- */
-struct abcsym *abc_new(struct abctune *t,
- char *text,
- char *comment)
-{
- struct abcsym *s;
-
- s = alloc_f(sizeof *s + client_sz);
- memset(s, 0, sizeof *s + client_sz);
- s->tune = t;
+ s = getarena(sizeof(struct SYMBOL));
+ memset(s, 0, sizeof(struct SYMBOL));
if (text) {
- s->text = alloc_f(strlen(text) + 1);
+ s->text = getarena(strlen(text) + 1);
strcpy(s->text, text);
}
- if (comment) {
- s->comment = alloc_f(strlen(comment) + 1);
- strcpy(s->comment, comment);
- }
- if (!t->last_sym) {
- t->first_sym = s;
+ if (!parse.last_sym) {
+ parse.first_sym = s;
} else {
- if ((s->next = t->last_sym->next) != NULL)
- s->next->prev = s;
- t->last_sym->next = s;
- s->prev = t->last_sym;
- }
- last_sym = t->last_sym = s;
- s->state = abc_state;
+ if ((s->abc_next = parse.last_sym->abc_next) != NULL)
+ s->abc_next->abc_prev = s;
+ parse.last_sym->abc_next = s;
+ s->abc_prev = parse.last_sym;
+ }
+ last_sym = parse.last_sym = s;
+ s->abc_type = type;
+ s->state = parse.abc_state;
+ s->fn = abc_fn;
s->linenum = linenum;
s->colnum = colnum;
return s;
}
-/* get the ABC version */
-static void get_vers(char *p)
+/* -- parse an ABC line -- */
+void abc_parse(char *p, char *fname, int ln)
{
- int i, j,k;
-
- i = j = k = 0;
- if (sscanf(p, "%d.%d.%d", &i, &j, &k) != 3)
- if (sscanf(p, "%d.%d", &i, &j) != 2)
- sscanf(p, "%d", &i);
- abc_vers = (i << 16) + (j << 8) + k;
-}
-
-/* -- parse an ABC file -- */
-struct abctune *abc_parse(char *file_api)
-{
- struct abctune *first_tune = NULL;
- struct abctune *t, *last_tune;
- /* saved global variables */
- int g_abc_vers, g_ulen, g_microscale;
- char *p;
- char g_char_tb[128];
-
- /* initialize */
- file = file_api;
- t = NULL;
- abc_state = ABC_S_GLOBAL;
- if (level_f)
- level_f(0);
- linenum = 0;
- last_tune = NULL;
- g_abc_vers = g_ulen = g_microscale = 0; /* (have gcc happy) */
-
- /* scan till end of file */
- for (;;) {
- if ((p = get_line()) == NULL) {
- if (abc_state == ABC_S_HEAD) {
- syntax("Unexpected EOF in header definition",
- p);
- severity = 1;
- }
- if (t)
- t->abc_vers = abc_vers;
- if (abc_state != ABC_S_GLOBAL) {
- abc_vers = g_abc_vers;
- ulen = g_ulen;
- microscale = g_microscale;
- memcpy(char_tb, g_char_tb, sizeof g_char_tb);
- }
- break; /* done */
- }
+ abc_fn = fname;
+ linenum = ln;
+ abc_line = p;
- /* start a new tune if not done */
- if (!t) {
- if (*p == '\0')
- continue;
- t = alloc_f(sizeof *t);
- memset(t, 0 , sizeof *t);
- if (!last_tune)
- first_tune = t;
- else
- last_tune->next = t;
- last_tune = t;
- p_micro = t->micro_tb;
- meter = 0;
- }
-
- /* parse the music line */
- switch (parse_line(t, p)) {
- case 2: /* start of tune */
- g_abc_vers = abc_vers;
- g_ulen = ulen;
- g_microscale = microscale;
- memcpy(g_char_tb, char_tb, sizeof g_char_tb);
- break;
- case 1: /* end of tune */
- t->abc_vers = abc_vers;
- abc_state = ABC_S_GLOBAL;
- t = NULL;
- abc_vers = g_abc_vers;
- ulen = g_ulen;
- microscale = g_microscale;
- memcpy(char_tb, g_char_tb, sizeof g_char_tb);
- if (level_f)
- level_f(0);
- if (dc.n > 0)
- syntax("Decoration without symbol", 0);
- dc.n = dc.h = dc.s = 0;
- break;
- }
+ /* parse the music line */
+ switch (parse_line(p)) {
+ case 2: /* start of tune (X:) */
+ g_abc_vers = parse.abc_vers;
+ g_ulen = ulen;
+ g_microscale = microscale;
+
+ meter = 2;
+ memcpy(g_char_tb, char_tb, sizeof g_char_tb);
+ memcpy(g_deco_tb, parse.deco_tb, sizeof g_deco_tb);
+ memcpy(g_micro_tb, parse.micro_tb, sizeof g_micro_tb);
+ break;
+ case 1: /* end of tune */
+ if (parse.first_sym) {
+ do_tune();
+ parse.first_sym = parse.last_sym = NULL;
+ }
+ parse.abc_state = ABC_S_GLOBAL;
+ parse.abc_vers = g_abc_vers;
+ ulen = g_ulen;
+ microscale = g_microscale;
+ memcpy(char_tb, g_char_tb, sizeof g_char_tb);
+ memcpy(parse.deco_tb, g_deco_tb, sizeof parse.deco_tb);
+ memcpy(parse.micro_tb, g_micro_tb, sizeof parse.micro_tb);
+ lvlarena(0);
+ if (dc.n > 0)
+ syntax("Decoration without symbol", 0);
+ dc.n = 0;
+ break;
}
- return first_tune;
}
-/* -- cut off after % and remove trailing blanks -- */
-static char *decomment_line(char *p)
+/* treat the end of file */
+void abc_eof(void)
{
- char *q, c, *comment = NULL;
-
- q = p;
- for (;;) {
- c = *p;
- if (c == '\0')
- break;
- if (c == '\\') {
- p++;
- if (*p == '\0')
- return 0;
- p++;
- continue;
- }
- if (c == '%') {
- if (keep_comment) {
- comment = p + 1;
- break;
- }
- break;
- }
- if (c == '"') {
- for (;;) {
- p++;
- if (*p == '\0')
- break;
- if (*p == '"' && p[-1] != '\\') {
- p++;
- break;
- }
- }
- } else {
- p++;
- }
+// if (parse.abc_state == ABC_S_HEAD)
+// severity = 1;
+ do_tune();
+ parse.first_sym = parse.last_sym = NULL;
+ if (parse.abc_state != ABC_S_GLOBAL) {
+ parse.abc_vers = g_abc_vers;
+ ulen = g_ulen;
+ microscale = g_microscale;
+ memcpy(char_tb, g_char_tb, sizeof g_char_tb);
}
-
- /* remove the trailing blanks */
- while (p > q) {
- c = *--p;
- if (!isspace((unsigned char) c)) {
- p[1] = '\0';
- break;
- }
- }
- return comment;
}
/* -- treat the broken rhythm '>' and '<' -- */
-static void broken_rhythm(struct note *note,
+static void broken_rhythm(struct SYMBOL *s,
int num) /* >0: do dot, <0: do half */
{
+ struct notes *notes = &s->u.note;
int l, m, n;
num *= 2;
@@ -461,19 +219,19 @@
if (num == 6)
num = 8;
n = num * 2 - 1;
- for (m = 0; m <= note->nhd; m++)
- note->lens[m] = (note->lens[m] * n) / num;
+ for (m = 0; m <= s->nhd; m++)
+ notes->notes[m].len = (notes->notes[m].len * n) / num;
} else {
n = -num;
if (n == 6)
n = 8;
- for (m = 0; m <= note->nhd; m++)
- note->lens[m] /= n;
+ for (m = 0; m <= s->nhd; m++)
+ notes->notes[m].len /= n;
}
- l = note->lens[0];
- for (m = 1; m <= note->nhd; m++)
- if (note->lens[m] < l)
- l = note->lens[m];
+ l = notes->notes[0].len;
+ for (m = 1; m <= s->nhd; m++)
+ if (notes->notes[m].len < l)
+ l = notes->notes[m].len;
}
/* -- check for the '!' as end of line (ABC2Win) -- */
@@ -499,9 +257,11 @@
static char *parse_extra(char *p,
char **p_name,
char **p_middle,
- char **p_lines,
+ char **p_stlines,
char **p_scale,
- char **p_octave)
+ char **p_octave,
+ char **p_cue,
+ char **p_map)
{
for (;;) {
if (strncmp(p, "clef=", 5) == 0
@@ -513,11 +273,13 @@
if (*p_name)
syntax("Double clef name", p);
*p_name = p;
- } else if (strncmp(p, "microscale=", 11) == 0) {
+ } else if (strncmp(p, "microscale=", 11) == 0
+ || strncmp(p, "uscale=", 7) == 0) {
int i;
- i = atoi(p + 11);
- if (i < 4 || i > 256)
+ p += p[0] == 'm' ? 11 : 7;
+ i = atoi(p);
+ if (i < 4 || i >= 256)
syntax("Invalid value in microscale=", p);
else
microscale = i;
@@ -531,16 +293,51 @@
syntax("Double octave=", p);
*p_octave = p + 7;
} else if (strncmp(p, "stafflines=", 11) == 0) {
- if (*p_lines)
+ int l;
+ char *q;
+
+ if (*p_stlines)
syntax("Double stafflines", p);
- *p_lines = p + 11;
+ p += 11;
+ if (isdigit((unsigned char) *p)) {
+ switch (atoi(p)) {
+ case 0: *p_stlines = "..."; break;
+ case 1: *p_stlines = "..|"; break;
+ case 2: *p_stlines = ".||"; break;
+ case 3: *p_stlines = ".|||"; break;
+ case 4: *p_stlines = "||||"; break;
+ case 5: *p_stlines = "|||||"; break;
+ case 6: *p_stlines = "||||||"; break;
+ case 7: *p_stlines = "|||||||"; break;
+ case 8: *p_stlines = "||||||||"; break;
+ default:
+ syntax("Bad number of lines", p);
+ break;
+ }
+ } else {
+ q = p;
+ while (!isspace((unsigned char) *p) && *p != '\0')
+ p++;
+ l = p - q;
+ *p_stlines = getarena(l + 1);
+ strncpy(*p_stlines, q, l);
+ (*p_stlines)[l] = '\0';
+ }
} else if (strncmp(p, "staffscale=", 11) == 0) {
if (*p_scale)
syntax("Double staffscale", p);
*p_scale = p + 11;
- } else if (strncmp(p, "transpose=", 10) == 0
- || strncmp(p, "t=", 2) == 0) {
- ; /* ignored */
+ } else if (strncmp(p, "cue=", 4) == 0) {
+ if (*p_cue)
+ syntax("Double cue", p);
+ *p_cue = p + 4;
+ } else if (strncmp(p, "map=", 4) == 0) {
+ if (*p_map)
+ syntax("Double map", p);
+ *p_map = p + 4;
+// } else if (strncmp(p, "transpose=", 10) == 0
+// || strncmp(p, "t=", 2) == 0) {
+// ; /* ignored - abcMIDI */
} else {
break;
}
@@ -556,12 +353,12 @@
/* -- parse a decoration 'xxx' -- */
static char *get_deco(char *p,
- unsigned char *p_deco)
+ unsigned char *p_dc)
{
char *q, sep, **t;
unsigned i, l;
- *p_deco = 0;
+ *p_dc = 0;
q = p;
sep = q[-1];
if (char_tb[(unsigned char) sep] == CHAR_DECOS) {
@@ -582,26 +379,26 @@
l = p - q;
if (*p == sep)
p++;
- for (i = 1, t = &deco_tb[1];
- *t && i < 128;
+ for (i = 1, t = &parse.deco_tb[1];
+ *t && i < DC_NAME_SZ;
i++, t++) {
if (strlen(*t) == l
&& strncmp(*t, q, l) == 0) {
- *p_deco = i + 128;
+ *p_dc = i + 128;
return p;
}
}
/* new decoration */
- if (i < 128) {
- if (level_f && abc_state != ABC_S_GLOBAL)
- level_f(0);
- *t = alloc_f(l + 1);
- if (level_f && abc_state != ABC_S_GLOBAL)
- level_f(1);
+ if (i < DC_NAME_SZ) {
+// if (parse.abc_state != ABC_S_GLOBAL)
+// lvlarena(0);
+ *t = getarena(l + 1);
+// if (parse.abc_state != ABC_S_GLOBAL)
+// lvlarena(1);
memcpy(*t, q, l);
(*t)[l] = '\0';
- *p_deco = i + 128;
+ *p_dc = i + 128;
} else {
syntax("Too many decoration types", q);
}
@@ -610,20 +407,20 @@
/* -- parse a list of accidentals (K:) -- */
static char *parse_acc(char *p,
- struct abcsym *s)
+ struct SYMBOL *s)
{
- int pit, len, acc, nostem;
+ int pit, acc;
unsigned nacc;
- if (s->u.key.empty == 2)
- syntax("cannot have 'none' and a list of accidentals", p);
nacc = 0;
for (;;) {
if (nacc >= sizeof s->u.key.pits) {
syntax("Too many accidentals", p);
break;
}
- p = parse_basic_note(p, &pit, &len, &acc, &nostem);
+ p = parse_acc_pit(p, &pit, &acc);
+ if (acc < 0)
+ break;
s->u.key.pits[nacc] = pit;
s->u.key.accs[nacc++] = acc;
while (isspace((unsigned char) *p))
@@ -640,11 +437,9 @@
}
/* -- parse a clef (K: or V:) -- */
-static void parse_clef(struct abcsym *s,
+static void parse_clef(struct SYMBOL *s,
char *name,
- char *middle,
- char *lines,
- char *scale)
+ char *middle)
{
int clef = -1;
int transpose = 0;
@@ -658,7 +453,7 @@
switch (*name) {
case '\"':
name = get_str(str, name, sizeof str);
- s->u.clef.name = alloc_f(strlen(str) + 1);
+ s->u.clef.name = getarena(strlen(str) + 1);
strcpy(s->u.clef.name, str);
clef = TREBLE;
break;
@@ -689,6 +484,7 @@
break;
case 'P':
clef = PERC;
+ clef_line = 3;
break;
}
if (clef >= 0) {
@@ -725,6 +521,10 @@
name += 5;
} else if (!strncmp(name, "perc", 4)) {
clef = PERC;
+ clef_line = 3;
+ name += 4;
+ } else if (!strncmp(name, "auto", 4)) {
+ clef = AUTOCLEF;
name += 4;
} else if (strncmp(name, "none", 4) == 0) {
clef = TREBLE;
@@ -733,19 +533,13 @@
name += 4;
} else {
syntax("Unknown clef", name);
+ clef = TREBLE;
}
}
if (clef >= 0) {
- switch (*name) {
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
+ if (isdigit((unsigned char) *name))
clef_line = *name++ - '0';
- break;
- }
if (name[1] == '8') {
switch (*name) {
case '^':
@@ -763,13 +557,15 @@
}
if (middle) {
- int pit, len, acc, nostem, l;
+ int pit, acc, l;
static const char line_tb[7] =
{ALTO, TREBLE, ALTO, BASS, ALTO, BASS, ALTO};
warn = middle;
/* 'middle=' */
- parse_basic_note(middle, &pit, &len, &acc, &nostem);
+ parse_acc_pit(middle, &pit, &acc);
+ if (acc < 0) // if error
+ pit = 22;
if (clef < 0)
clef = line_tb[(pit + 7) % 7];
@@ -799,26 +595,6 @@
s->u.clef.type = clef;
s->u.clef.line = clef_line;
s->u.clef.transpose = transpose;
- s->u.clef.stafflines = -1;
- s->u.clef.staffscale = 0;
- if (lines) {
- int l;
-
- l = atoi(lines);
- if ((unsigned) l < 10)
- s->u.clef.stafflines = l;
- else
- syntax("Bad value of stafflines", lines);
- }
- if (scale) {
- float sc;
-
- sc = atof(scale);
- if (sc >= 0.5 && sc <= 3)
- s->u.clef.staffscale = sc;
- else
- syntax("Bad value of staffscale", scale);
- }
if (warn) {
int sev_sav;
@@ -848,30 +624,25 @@
/* -- parse a 'K:' -- */
static void parse_key(char *p,
- struct abcsym *s)
+ struct SYMBOL *s)
{
- int sf, mode;
- char *clef_name, *clef_middle, *clef_lines, *clef_scale;
- char *p_octave;
+ int sf, empty, instr;
+// int mode;
+ char *clef_name, *clef_middle, *clef_stlines, *clef_scale;
+ char *p_octave, *p_cue, *p_map;
+
+ // set important default values
+// s->u.key.stafflines = "|||||";
+ s->u.key.octave = NO_OCTAVE;
if (*p == '\0') {
- s->u.key.empty = 2;
+ s->u.key.empty = 1;
return;
}
- if (strncasecmp(p, "none", 4) == 0) {
- s->u.key.empty = 2;
- p += 4;
- while (isspace((unsigned char) *p))
- p++;
- if (*p == '\0')
- return;
- }
- clef_name = clef_middle = clef_lines = clef_scale = NULL;
- p_octave = NULL;
- p = parse_extra(p, &clef_name, &clef_middle, &clef_lines,
- &clef_scale, &p_octave);
sf = 0;
- mode = MAJOR;
+// mode = 0;
+ empty = 0;
+ instr = 0;
switch (*p++) {
case 'F': sf = -1; break;
case 'B': sf++;
@@ -882,55 +653,56 @@
case 'C': break;
case 'H':
if (*p == 'P') {
- mode = BAGPIPE;
+ instr = K_HP;
p++;
} else if (*p == 'p') {
- mode = BAGPIPE + 1;
+ instr = K_Hp;
sf = 2;
p++;
} else {
syntax("Unknown bagpipe-like key", p);
}
break;
- case '^':
- case '_':
- case '=':
- p--; /* explicit accidentals */
- break;
- case '\0':
- if (s->u.key.empty == 0)
- s->u.key.empty = 1;
- p--;
+ case 'P':
+ instr = K_DRUM;
+ p++;
break;
+ case 'n':
+ if (strncmp(p, "one", 3) == 0) { // none
+ empty = 2;
+ p += 3;
+ while (isspace((unsigned char) *p))
+ p++;
+ if (*p == '\0') {
+ s->u.key.empty = empty;
+ return;
+ }
+ break;
+ }
+ // fall thru
default:
p--;
- if (s->u.key.empty != 2)
- syntax("Key not recognized", p);
+ empty = 1;
break;
}
- if (*p == '#') {
- sf += 7;
- p++;
- } else if (*p == 'b') {
- sf -= 7;
- p++;
- }
+ s->u.key.empty = empty;
- while (*p != '\0') {
+ if (!empty) {
+ if (*p == '#') {
+ sf += 7;
+ p++;
+ } else if (*p == 'b') {
+ sf -= 7;
+ p++;
+ }
while (isspace((unsigned char) *p))
p++;
- if (*p == '\0')
- break;
- p = parse_extra(p, &clef_name, &clef_middle, &clef_lines,
- &clef_scale, &p_octave);
- if (*p == '\0')
- break;
switch (*p) {
case 'a':
case 'A':
if (strncasecmp(p, "aeo", 3) == 0) {
sf -= 3;
- mode = 5;
+// mode = 5;
break;
}
goto unk;
@@ -938,21 +710,14 @@
case 'D':
if (strncasecmp(p, "dor", 3) == 0) {
sf -= 2;
- mode = 1;
- break;
- }
- goto unk;
- case 'e':
- case 'E':
- if (strncasecmp(p, "exp", 3) == 0) {
- s->u.key.exp = 1;
+// mode = 1;
break;
}
goto unk;
case 'i':
case 'I':
if (strncasecmp(p, "ion", 3) == 0) {
- mode = 0;
+// mode = 0;
break;
}
goto unk;
@@ -960,12 +725,12 @@
case 'L':
if (strncasecmp(p, "loc", 3) == 0) {
sf -= 5;
- mode = 6;
+// mode = 6;
break;
}
if (strncasecmp(p, "lyd", 3) == 0) {
sf += 1;
- mode = 3;
+// mode = 3;
break;
}
goto unk;
@@ -975,13 +740,13 @@
break;
if (strncasecmp(p, "mix", 3) == 0) {
sf -= 1;
- mode = 4;
+// mode = 4;
break;
}
if (strncasecmp(p, "min", 3) == 0
|| !isalpha((unsigned char) p[1])) { /* 'm' alone */
sf -= 3;
- mode = MINOR;
+// mode = 5;
break;
}
goto unk;
@@ -989,24 +754,43 @@
case 'P':
if (strncasecmp(p, "phr", 3) == 0) {
sf -= 4;
- mode = 2;
+// mode = 2;
break;
}
goto unk;
- case '^':
- case '_':
- case '=':
- p = parse_acc(p, s); /* explicit accidentals */
- continue;
default:
- unk:
- syntax("Unknown token in key specifier", p);
- while (!isspace((unsigned char) *p) && *p != '\0')
+unk:
+ empty = 1; // (local value)
+ break;
+ }
+ if (!empty) {
+ while (isalpha((unsigned char) *p))
+ p++;
+ while (isspace((unsigned char) *p))
p++;
- continue;
}
- while (isalpha((unsigned char) *p))
- p++;
+
+ // [exp] accidentals
+ if (strncmp(p, "exp ", 4) == 0) {
+ p += 4;
+ while (isspace((unsigned char) *p))
+ p++;
+ if (*p == '\0')
+ syntax("no accidental after 'exp'", p);
+ s->u.key.exp = 1;
+ }
+ if (s->u.key.exp && strncmp(p, "none", 4) == 0) {
+ sf = 0;
+ p += 4;
+ while (isspace((unsigned char) *p))
+ p++;
+ } else switch (*p) {
+ case '^':
+ case '_':
+ case '=':
+ p = parse_acc(p, s); /* accidentals */
+ break;
+ }
}
if (sf > 7 || sf < -7) {
@@ -1016,26 +800,54 @@
else
sf += 12;
}
+
+ // extra parameters
+ clef_name = clef_middle = clef_stlines = clef_scale = NULL;
+ p_octave = p_cue = p_map = NULL;
+ parse_extra(p, &clef_name, &clef_middle, &clef_stlines,
+ &clef_scale, &p_octave, &p_cue, &p_map);
+
s->u.key.sf = sf;
- s->u.key.mode = mode;
+// s->u.key.mode = mode;
+ s->u.key.instr = instr;
s->u.key.octave = parse_octave(p_octave);
+ if (p_cue) {
+ if (strncmp(p_cue, "on", 2) == 0)
+ s->u.key.cue = 1;
+ else
+ s->u.key.cue = -1;
+ }
+ if (clef_stlines)
+ s->u.key.stafflines = clef_stlines;
+ if (clef_scale) {
+ float sc;
- if (clef_name || clef_middle || clef_lines || clef_scale) {
- s = abc_new(s->tune, NULL, NULL);
- s->type = ABC_T_CLEF;
- parse_clef(s, clef_name, clef_middle, clef_lines,
- clef_scale);
+ sc = atof(clef_scale);
+ if (sc >= 0.5 && sc <= 3)
+ s->u.key.staffscale = sc;
+ else
+ syntax("Bad value of staffscale", clef_scale);
+ }
+ if (clef_name || clef_middle) {
+ s = abc_new(ABC_T_CLEF, NULL);
+ parse_clef(s, clef_name, clef_middle);
+ }
+ if (p_map) {
+ strcpy(tex_buf, "%%voicemap ");
+ get_str(&tex_buf[11], p_map, TEX_BUF_SZ - 12);
+ abc_new(ABC_T_PSCOM, tex_buf);
}
}
/* -- set default length from 'L:' -- */
static char *get_len(char *p,
- struct abcsym *s)
+ struct SYMBOL *s)
{
int l1, l2, d;
char *error_txt = NULL;
if (strcmp(p, "auto") == 0) { /* L:auto */
+ ulen = 15120; // 2*2*2*2*3*3*3*5*7
s->u.length.base_length = -1;
return error_txt;
}
@@ -1067,123 +879,26 @@
return error_txt;
}
-/* -- get a new line from the current file in memory -- */
-static char *get_line(void)
-{
- int l;
- char *p, *q;
-
- p = file;
- if (*p == '\0')
- return 0;
- abc_line = p;
- linenum++;
-
- /* handle %%begin .. %%end */
- if (strncmp(p, "%%begin", 7) == 0) {
- for (;;) {
- while (*p != '\0'
- && *p != '\n')
- p++;
- if (*p == '\0') {
- syntax("No %%end after %%begin", 0);
- break;
- }
- linenum++;
- p++;
- if (strncmp(p, "%%end", 5) == 0) {
- p[-1] = '\0';
- while (*p != '\0'
- && *p != '\n')
- p++;
- if (*p != '\0')
- *p++ = '\0';
- break;
- }
- }
- file = p;
- return abc_line;
- }
-
- /* set the end of line and
- * memorize the beginning of the next line */
- while (*p != '\0'
- && *p != '\n')
- p++;
- if (*p != '\0')
- *p++ = '\0';
- file = p;
-
- /* special case for continuation lines in ABC version 2.0 */
- if (abc_vers == (2 << 16)) {
- p = abc_line;
- for (;;) {
- while (*p != '\0') {
- if (*p == '"') {
- for (;;) {
- p++;
- if (*p == '\0')
- break;
- if (*p == '"' && p[-1] != '\\') {
- p++;
- break;
- }
- }
- continue;
- }
- if (*p == '\\'
- && p[1] != '\\'
- && p[1] != '%') {
- q = p + 1;
- while (isspace((unsigned char) *q))
- q++;
- if (*q == '\0' || *q == '%')
- break;
- p = q;
- continue;
- }
- p++;
- }
- if (*p == '\0')
- break;
-
- /* continuation found */
- q = file;
- if (*q == '\0')
- break;
- linenum++;
- while (*q != '\0'
- && *q != '\n')
- q++;
- l = q - file;
- memmove(p, file, l); /* concatenate */
- p[l] = '\0';
- if (*q == '\0')
- break;
- file = q + 1;
- }
- }
- return abc_line;
-}
-
/* -- parse a 'M:' -- */
static char *parse_meter(char *p,
- struct abcsym *s)
+ struct SYMBOL *s)
{
int m1, m2, d, wmeasure, nm, in_parenth;
unsigned i;
char *q;
-static char *top_err = "Cannot identify meter top";
+static char top_err[] = "Cannot identify meter top";
if (*p == '\0')
return "Empty meter string";
nm = 0;
in_parenth = 0;
- wmeasure = 0;
m1 = 0;
if (strncmp(p, "none", 4) == 0) {
p += 4; /* no meter */
- } else while (*p != '\0') {
+ wmeasure = 1; /* simplify measure numbering and MREST conversion */
+ } else {
+ wmeasure = 0;
+ while (*p != '\0') {
if (*p == '=')
break;
if (nm >= MAX_MEASURE)
@@ -1278,6 +993,7 @@
p++;
else if (*p == '+')
s->u.meter.meter[nm++].top[0] = *p++;
+ }
}
meter = m1;
if (*p == '=') {
@@ -1291,10 +1007,10 @@
s->u.meter.wmeasure = wmeasure;
s->u.meter.nmeter = nm;
- /* if in the header, change the unit note length */
- if (abc_state == ABC_S_HEAD && ulen == 0) {
+ /* in the tune header, change the unit note length */
+ if (parse.abc_state == ABC_S_HEAD && ulen == 0) {
if (wmeasure >= BASE_LEN * 3 / 4
- || wmeasure == 0)
+ || wmeasure <= 1)
ulen = BASE_LEN / 8;
else
ulen = BASE_LEN / 16;
@@ -1345,72 +1061,82 @@
/* -- parse a tempo (Q:) -- */
static char *parse_tempo(char *p,
- struct abcsym *s)
+ struct SYMBOL *s)
{
- int l;
- char *q, str[80];
+ char c, str[80];
+ int i, l, n, top, bot;
/* string before */
if (*p == '"') {
p = get_str(str, p, sizeof str);
- s->u.tempo.str1 = alloc_f(strlen(str) + 1);
+ s->u.tempo.str1 = getarena(strlen(str) + 1);
strcpy(s->u.tempo.str1, str);
}
/* beat */
if (*p == 'C' || *p == 'c'
|| *p == 'L' || *p == 'l') {
- int len;
-
+ s->u.tempo.beats[0] = ulen;
+ if (parse.abc_vers >= (2 << 16))
+ syntax("Deprecated Q: value", p);
p++;
- if (*p != '=')
- goto inval;
- p = parse_len(p + 1, &len);
- if (len <= 0)
- goto inval;
- s->u.tempo.length[0] = len * ulen / BASE_LEN;
while (isspace((unsigned char) *p))
p++;
- if (abc_vers >= (2 << 16))
- syntax("Deprecated Q: value", p);
- } else if (isdigit((unsigned char) *p) && strchr(p, '/') != 0) {
- unsigned i;
-
- i = 0;
- while (isdigit((unsigned char) *p)) {
- int top, bot, n;
-
- if (sscanf(p, "%d /%d%n", &top, &bot, &n) != 2
- || bot <= 0)
- goto inval;
- l = (BASE_LEN * top) / bot;
- if (l <= 0
- || i >= sizeof s->u.tempo.length
- / sizeof s->u.tempo.length[0])
+ if (*p != '=')
+ goto inval;
+ c = '=';
+ p--;
+ } else if (isdigit((unsigned char) *p)) {
+ if (strchr(p, '/') != NULL) {
+ i = 0;
+ while (isdigit((unsigned char) *p)) {
+ if (sscanf(p, "%d/%d%n", &top, &bot, &n) != 2
+ || bot <= 0)
+ goto inval;
+ l = (BASE_LEN * top) / bot;
+ if (l <= 0
+ || i >= sizeof s->u.tempo.beats
+ / sizeof s->u.tempo.beats[0])
+ goto inval;
+ s->u.tempo.beats[i++] = l;
+ p += n;
+ while (isspace((unsigned char) *p))
+ p++;
+ }
+ c = *p;
+ if (c != '=')
goto inval;
- s->u.tempo.length[i++] = l;
- p += n;
- while (isspace((unsigned char) *p))
- p++;
+ } else {
+ s->u.tempo.beats[0] = ulen;
+ if (parse.abc_vers >= (2 << 16))
+ syntax("Deprecated Q: value", p);
+ c = '=';
+ p--;
}
+ } else {
+ c = '\0';
}
- /* tempo value ('Q:beat=value' or 'Q:value') */
- if (*p == '=') {
+ /* tempo value */
+ if (c == '=') {
p++;
- while (isspace((unsigned char) *p))
- p++;
- }
- if (*p != '\0' && *p != '"') {
- q = p;
- while (*p != '"' && *p != '\0')
- p++;
- while (isspace((unsigned char) p[-1]))
- p--;
- l = p - q;
- s->u.tempo.value = alloc_f(l + 1);
- strncpy(s->u.tempo.value, q, l);
- s->u.tempo.value[l] = '\0';
+ if (strncmp(p, "ca. ", 4) == 0) {
+ s->u.tempo.circa = 1;
+ p += 4;
+ }
+ if (sscanf(p, "%d/%d%n", &top, &bot, &n) == 2) {
+ if (bot <= 0)
+ goto inval;
+ l = (BASE_LEN * top) / bot;
+ if (l <= 0)
+ goto inval;
+ s->u.tempo.new_beat = l;
+ } else {
+ if (sscanf(p, "%d%n", &top, &n) != 1)
+ goto inval;
+ s->u.tempo.tempo = top;
+ }
+ p += n;
while (isspace((unsigned char) *p))
p++;
}
@@ -1418,17 +1144,10 @@
/* string after */
if (*p == '"') {
p = get_str(str, p, sizeof str);
- s->u.tempo.str2 = alloc_f(strlen(str) + 1);
+ s->u.tempo.str2 = getarena(strlen(str) + 1);
strcpy(s->u.tempo.str2, str);
}
- if (!s->u.tempo.str1 && !s->u.tempo.str2
- && s->u.tempo.length[0] == 0) {
- if (s->u.tempo.value == 0)
- return "Empty tempo";
- if (abc_vers >= (2 << 16))
- syntax("Deprecated Q: value", p);
- }
return 0;
inval:
return "Invalid tempo";
@@ -1436,7 +1155,7 @@
/* -- get a user defined symbol (U:) -- */
static char *get_user(char *p,
- struct abcsym *s)
+ struct SYMBOL *s)
{
unsigned char c;
char *value;
@@ -1475,9 +1194,11 @@
p++;
/*fixme: 'U: = "text"' is not treated */
get_deco(p, &s->u.user.value);
+ if (!s->u.user.value)
+ return 0;
/* treat special pseudo decorations */
- value = deco_tb[s->u.user.value - 128];
+ value = parse.deco_tb[s->u.user.value - 128];
if (strcmp(value, "beambreak") == 0)
char_tb[c] = CHAR_SPAC;
else if (strcmp(value, "ignore") == 0)
@@ -1493,13 +1214,12 @@
/* -- parse the voice parameters (V:) -- */
static char *parse_voice(char *p,
- struct abcsym *s)
+ struct SYMBOL *s)
{
int voice;
char *error_txt = NULL;
- char name[VOICE_NAME_SZ];
- char *clef_name, *clef_middle, *clef_lines, *clef_scale;
- char *p_octave;
+ char *clef_name, *clef_middle, *clef_stlines, *clef_scale;
+ char *p_octave, *p_cue, *p_map;
signed char *p_stem;
static struct kw_s {
char *name;
@@ -1530,7 +1250,7 @@
curvoice->microscale = microscale;
if (voice_tb[0].id[0] == '\0') {
- switch (s->prev->type) {
+ switch (s->abc_prev->abc_type) {
case ABC_T_EOLN:
case ABC_T_NOTE:
case ABC_T_REST:
@@ -1571,22 +1291,22 @@
s->u.voice.voice = voice;
/* if in tune, set the voice parameters */
- if (abc_state == ABC_S_TUNE) {
+ if (parse.abc_state == ABC_S_TUNE) {
ulen = curvoice->ulen;
microscale = curvoice->microscale;
}
/* parse the other parameters */
- clef_name = clef_middle = clef_lines = clef_scale = NULL;
- p_octave = NULL;
+ clef_name = clef_middle = clef_stlines = clef_scale = NULL;
+ p_octave = p_cue = p_map = NULL;
p_stem = &s->u.voice.stem;
for (;;) {
while (isspace((unsigned char) *p))
p++;
if (*p == '\0')
break;
- p = parse_extra(p, &clef_name, &clef_middle, &clef_lines,
- &clef_scale, &p_octave);
+ p = parse_extra(p, &clef_name, &clef_middle, &clef_stlines,
+ &clef_scale, &p_octave, &p_cue, &p_map);
if (*p == '\0')
break;
for (kw = kw_tb; kw->name; kw++) {
@@ -1601,14 +1321,14 @@
p += kw->len;
switch (kw->index) {
case 0: /* name */
- p = get_str(name, p, VOICE_NAME_SZ);
- s->u.voice.fname = alloc_f(strlen(name) + 1);
- strcpy(s->u.voice.fname, name);
+ p = get_str(tex_buf, p, TEX_BUF_SZ);
+ s->u.voice.fname = getarena(strlen(tex_buf) + 1);
+ strcpy(s->u.voice.fname, tex_buf);
break;
case 1: /* subname */
- p = get_str(name, p, VOICE_NAME_SZ);
- s->u.voice.nname = alloc_f(strlen(name) + 1);
- strcpy(s->u.voice.nname, name);
+ p = get_str(tex_buf, p, TEX_BUF_SZ);
+ s->u.voice.nname = getarena(strlen(tex_buf) + 1);
+ strcpy(s->u.voice.nname, tex_buf);
break;
case 2: /* merge */
s->u.voice.merge = 1;
@@ -1653,25 +1373,46 @@
}
s->u.voice.octave = parse_octave(p_octave);
+ if (p_cue) {
+ if (strncmp(p_cue, "on", 2) == 0)
+ s->u.voice.cue = 1;
+ else
+ s->u.voice.cue = -1;
+ }
+ if (clef_stlines)
+ s->u.voice.stafflines = clef_stlines;
+// else
+// s->u.voice.stafflines = "|||||";
+ if (clef_scale) {
+ float sc;
- if (clef_name || clef_middle || clef_lines || clef_scale) {
- s = abc_new(s->tune, NULL, NULL);
- s->type = ABC_T_CLEF;
- parse_clef(s, clef_name, clef_middle, clef_lines,
- clef_scale);
+ sc = atof(clef_scale);
+ if (sc >= 0.5 && sc <= 3)
+ s->u.voice.staffscale = sc;
+ else
+ syntax("Bad value of staffscale", clef_scale);
+ }
+ if (clef_name || clef_middle) {
+ s = abc_new(ABC_T_CLEF, NULL);
+ parse_clef(s, clef_name, clef_middle);
+ }
+ if (p_map) {
+ strcpy(tex_buf, "%%voicemap ");
+ get_str(&tex_buf[11], p_map, TEX_BUF_SZ - 12);
+ abc_new(ABC_T_PSCOM, tex_buf);
}
return error_txt;
}
/* -- parse a bar -- */
-static char *parse_bar(struct abctune *t,
- char *p)
+static char *parse_bar(char *p)
{
- struct abcsym *s;
- int bar_type;
+ struct SYMBOL *s;
+ char *q;
+ int bar_type, i;
char repeat_value[32];
- p--;
+ q = --p; // keep the first char
bar_type = 0;
for (;;) {
switch (*p++) {
@@ -1714,19 +1455,37 @@
curvoice = &voice_tb[curvoice->mvoice];
vover = 0;
}
- s = abc_new(t, gchord, NULL);
- if (gchord) {
- if (free_f)
- free_f(gchord);
+ s = abc_new(ABC_T_BAR, gchord);
+ if (gchord)
gchord = NULL;
+
+ /* handle the repeat sequences */
+ if (bar_type == B_COL) {
+ bar_type = B_BAR;
+ s->u.bar.dotted = 1;
+ } else {
+ if (*q == ']') { /* repeat bar stop */
+ i = p - q - 1;
+ if (i > 0) /* remove the starting ']' */
+ s->u.bar.type &= (1 << (i * 4)) - 1;
+ s->flags |= ABC_F_RBSTOP;
+ s->sflags |= S_RBSTOP;
+ } else if ((bar_type & 0x0f) == B_COL /* left or */
+ || *q == ':') { /* right repeat bar */
+ s->flags |= ABC_F_RBSTOP;
+ s->sflags |= S_RBSTOP;
+ if (*q == ':') /* right repeat bar */
+ s->sflags |= S_RRBAR;
+ }
}
- s->type = ABC_T_BAR;
+
s->u.bar.type = bar_type;
if (dc.n > 0) {
memcpy(&s->u.bar.dc, &dc, sizeof s->u.bar.dc);
- dc.n = dc.h = dc.s = 0;
+ dc.n = 0;
}
+
if (!lyric_started) {
lyric_started = 1;
s->flags |= ABC_F_LYRIC_START;
@@ -1755,57 +1514,53 @@
}
if (bar_type != B_OBRA
|| s->text) {
- s = abc_new(t, repeat_value, NULL);
- s->type = ABC_T_BAR;
+ s = abc_new(ABC_T_BAR, repeat_value);
s->u.bar.type = B_OBRA;
} else {
- s->text = alloc_f(strlen(repeat_value) + 1);
+ s->text = getarena(strlen(repeat_value) + 1);
strcpy(s->text, repeat_value);
}
s->u.bar.repeat_bar = 1;
+ s->flags |= ABC_F_RBSTART | ABC_F_RBSTOP;
+ s->sflags |= S_RBSTART | S_RBSTOP;
return p;
}
-/* -- parse note or rest with pitch and length -- */
-/* in case of error, 'accidental' is set to -1 */
-static char *parse_basic_note(char *p,
- int *pitch,
- int *length,
- int *accidental,
- int *stemless)
+// parse the note accidental and pitch
+char *parse_acc_pit(char *p,
+ int *pit,
+ int *acc)
{
- int pit, len, acc, nostem;
-
- acc = pit = nostem = 0;
-
/* look for accidental sign */
switch (*p) {
case '^':
p++;
if (*p == '^') {
p++;
- acc = A_DS;
+ *acc = A_DS;
} else {
- acc = A_SH;
+ *acc = A_SH;
}
break;
case '=':
p++;
- acc = A_NT;
+ *acc = A_NT;
break;
case '_':
p++;
if (*p == '_') {
p++;
- acc = A_DF;
+ *acc = A_DF;
} else {
- acc = A_FT;
+ *acc = A_FT;
}
break;
+ default:
+ *acc = 0;
}
/* look for microtone value */
- if (acc != 0
+ if (*acc != 0
&& (isdigit((unsigned char) *p)
|| (*p == '/' && microscale == 0))) {
int n, d;
@@ -1829,10 +1584,10 @@
d--;
d += (n - 1) << 8; /* short [ (n-1) | (d-1) ] */
for (n = 1; n < MAXMICRO; n++) {
- if (p_micro[n] == d)
+ if (parse.micro_tb[n] == d)
break;
- if (p_micro[n] == 0) {
- p_micro[n] = d;
+ if (parse.micro_tb[n] == 0) {
+ parse.micro_tb[n] = d;
break;
}
}
@@ -1841,7 +1596,7 @@
n = 0;
}
}
- acc += (n << 3);
+ *acc += (n << 3);
}
/* get the pitch */
@@ -1849,58 +1604,49 @@
char *p_n;
p_n = strchr(all_notes, *p);
- if (!p_n) {
- syntax(acc ? "Missing note after accidental"
+ if (!p_n || *p == '\0') {
+ syntax(*acc ? "Missing note after accidental"
: "Not a note", p);
- acc = -1;
+ *acc = -1;
if (*p == '\0')
p--;
} else {
- pit = p_n - all_notes + 16;
+ *pit = p_n - all_notes + 16;
}
p++;
}
while (*p == '\'') { /* eat up following ' chars */
- pit += 7;
+ *pit += 7;
p++;
}
while (*p == ',') { /* eat up following , chars */
- pit -= 7;
+ *pit -= 7;
p++;
}
- if (*p == '0') {
- nostem = 1;
- p++;
- }
- p = parse_len(p, &len);
-
- *pitch = pit;
- *length = len;
- *accidental = acc;
- *stemless = nostem;
return p;
}
/* -- parse the decorations of notes and bars -- */
-char *parse_deco(char *p,
- struct deco *deco)
+static char *parse_deco(char *p,
+ struct decos *deco,
+ int m) /* note index / -1 */
{
int n;
- unsigned char c, d;
+ unsigned char t;
n = deco->n;
for (;;) {
- c = (unsigned char) *p++;
- if (char_tb[c] != CHAR_DECO && char_tb[c] != CHAR_DECOS)
+ t = (unsigned char) *p++;
+ if (char_tb[t] != CHAR_DECO && char_tb[t] != CHAR_DECOS)
break;
- if (char_tb[c] == CHAR_DECOS) {
- p = get_deco(p, &d);
- c = d;
- }
- if (n >= MAXDC)
+ if (char_tb[t] == CHAR_DECOS)
+ p = get_deco(p, &t);
+ if (n >= MAXDC) {
syntax("Too many decorations for the note", p);
- else if (c != 0)
- deco->t[n++] = c;
+ } else if (t != 0) {
+ deco->tm[n].t = t;
+ deco->tm[n++].m = m;
+ }
}
deco->n = n;
return p - 1;
@@ -1909,8 +1655,8 @@
/* -- parse a decoration line (d: or s:) -- */
static char *parse_decoline(char *p)
{
- struct abcsym *is;
- unsigned char d;
+ struct SYMBOL *is;
+ unsigned char t;
int n;
if ((is = deco_cont) == NULL)
@@ -1926,24 +1672,24 @@
break;
switch (*p) {
case '|':
- while (is && (is->type != ABC_T_BAR
+ while (is && (is->abc_type != ABC_T_BAR
|| is->u.bar.type == B_OBRA))
- is = is->next;
+ is = is->abc_next;
if (!is) {
syntax("Not enough bar lines for deco line", p);
return NULL;
}
- is = is->next;
+ is = is->abc_next;
p++;
continue;
case '*':
- while (is && is->type != ABC_T_NOTE)
- is = is->next;
+ while (is && is->abc_type != ABC_T_NOTE)
+ is = is->abc_next;
if (!is) {
syntax("Not enough notes for deco line", p);
return NULL;
}
- is = is->next;
+ is = is->abc_next;
p++;
continue;
case '\\':
@@ -1961,16 +1707,16 @@
break;
default:
if (char_tb[(unsigned char) *p] == CHAR_DECOS)
- p = get_deco(p + 1, &d);
+ p = get_deco(p + 1, &t);
else
- d = (unsigned char) *p++;
+ t = (unsigned char) *p++;
break;
}
- /* store the decoration / gchord/annotation in the next note */
- while (is && (is->type != ABC_T_NOTE
+ /* store the decoration and gchord/annotation in the next note */
+ while (is && (is->abc_type != ABC_T_NOTE
|| (is->flags & ABC_F_GRACE)))
- is = is->next;
+ is = is->abc_next;
if (!is)
return "Not enough notes for deco line";
@@ -1979,14 +1725,10 @@
char *gch;
n = strlen(is->text);
- gch = alloc_f(n + strlen(gchord) + 2);
+ gch = getarena(n + strlen(gchord) + 2);
strcpy(gch, is->text);
gch[n] = '\n';
strcpy(gch + n + 1, gchord);
- if (free_f) {
- free_f(gchord);
- free_f(is->text);
- }
gchord = gch;
}
is->text = gchord;
@@ -1995,12 +1737,13 @@
n = is->u.note.dc.n;
if (n >= MAXDC) {
syntax("Too many decorations for the note", p);
- } else if (d != 0) {
- is->u.note.dc.t[n] = d;
- is->u.note.dc.n = n + 1;
+ } else if (t != 0) {
+ is->u.note.dc.tm[n].t = t;
+ is->u.note.dc.tm[n].m = -1;
+ is->u.note.dc.n = ++n;
}
}
- is = is->next;
+ is = is->abc_next;
}
return NULL;
}
@@ -2027,16 +1770,14 @@
/* many guitar chords: concatenate with '\n' */
l2 = strlen(gchord);
- gch = alloc_f(l2 + 1 + l + 1);
+ gch = getarena(l2 + 1 + l + 1);
strcpy(gch, gchord);
gch[l2++] = '\n';
strncpy(&gch[l2], q, l);
gch[l2 + l] = '\0';
- if (free_f)
- free_f(gchord);
gchord = gch;
} else {
- gchord = alloc_f(l + 1);
+ gchord = getarena(l + 1);
strncpy(gchord, q, l);
gchord[l] = '\0';
}
@@ -2047,12 +1788,13 @@
/* -- parse a note length -- */
static char *parse_len(char *p,
+ int dur_u,
int *p_len)
{
int len, fac;
char *q;
- len = BASE_LEN;
+ len = dur_u;
if (isdigit((unsigned char) *p)) {
len *= strtol(p, &q, 10);
if (len <= 0) {
@@ -2084,51 +1826,32 @@
/* -- parse a ABC line -- */
/* return 1 on end of tune, and 2 on start of new tune */
-static int parse_line(struct abctune *t,
- char *p)
+static int parse_line(char *p)
{
- struct abcsym *s;
- char *comment, *q, c;
- struct abcsym *last_note_sav = NULL;
- struct deco dc_sav;
+ struct SYMBOL *s;
+ char *q, c;
+ char *dot = NULL;
+ struct SYMBOL *last_note_sav = NULL;
+ struct decos dc_sav;
int i, flags, flags_sav = 0, slur;
static char qtb[10] = {0, 1, 3, 2, 3, 0, 2, 0, 3, 0};
colnum = 0;
switch (*p) {
case '\0': /* blank line */
- switch (abc_state) {
+ switch (parse.abc_state) {
case ABC_S_GLOBAL:
+ if (parse.last_sym
+ && parse.last_sym->abc_type != ABC_T_NULL)
+ abc_new(ABC_T_NULL, NULL);
case ABC_S_HEAD: /*fixme: may have blank lines in headers?*/
- if (keep_comment || abc_state == ABC_S_GLOBAL) {
- if (t->last_sym
- && t->last_sym->type != ABC_T_NULL) {
- s = abc_new(t, NULL, NULL);
- s->type = ABC_T_NULL;
- }
- }
return 0;
}
return 1;
case '%':
- if (p[1] == '@') { /* line number - see front.c */
- linenum = atol(p + 2);
- if (linenum == 0 && strncmp(file, "%abc-", 5) == 0)
- get_vers(file + 5);
- return 0;
- }
if (p[1] == '%') {
- if (strncmp(p + 2, "begin", 5) != 0)
- comment = decomment_line(p + 2);
- else
- comment = NULL;
- s = abc_new(t, p, comment);
- s->type = ABC_T_PSCOM;
+ s = abc_new(ABC_T_PSCOM, p);
p += 2; /* skip '%%' */
- if (strncasecmp(p, "abc-version ", 12) == 0) {
- get_vers(p + 12);
- return 0;
- }
if (strncasecmp(p, "decoration ", 11) == 0) {
p += 11;
while (isspace((unsigned char) *p))
@@ -2169,9 +1892,9 @@
= CHAR_LINEBREAK;
break;
case '<':
- if (strcmp(p, "") == 0)
+ if (strncmp(p, "", 6) == 0)
return 0;
- if (strcmp(p, "") == 0) {
+ if (strncmp(p, "", 5) == 0) {
char_tb['\n'] = CHAR_LINEBREAK;
p += 5;
break;
@@ -2186,6 +1909,19 @@
}
return 0;
}
+ if (strncasecmp(p, "microscale ", 11) == 0) {
+ int v;
+
+ p += 11;
+ while (isspace((unsigned char) *p))
+ p++;
+ sscanf(p, "%d", &v);
+ if (v < 4 || v >= 256 || v & 1)
+ syntax("Invalid value in %%microscale", p);
+ else
+ microscale = v;
+ return 0;
+ }
if (strncasecmp(p, "user ", 5) == 0) {
p += 5;
while (isspace((unsigned char) *p))
@@ -2197,25 +1933,20 @@
}
/* fall thru */
case '\\': /* abc2mtex specific lines */
- if (keep_comment) {
- s = abc_new(t, p, NULL);
- s->type = ABC_T_NULL;
- }
return 0; /* skip */
}
- comment = decomment_line(p);
/* header fields */
if (p[1] == ':'
&& *p != '|' && *p != ':') { /* not '|:' nor '::' */
int new_tune;
- new_tune = parse_info(t, p, comment);
+ new_tune = parse_info(p);
/* handle BarFly voice definition */
/* 'V:n ' */
if (*p != 'V'
- || abc_state != ABC_S_TUNE)
+ || parse.abc_state != ABC_S_TUNE)
return new_tune; /* (normal return) */
c = p[strlen(p) - 1];
if (c != '|' && c != ']')
@@ -2225,17 +1956,12 @@
while (isspace((unsigned char) *p))
p++;
}
- if (abc_state != ABC_S_TUNE) {
- if (keep_comment) {
- s = abc_new(t, p, comment);
- s->type = ABC_T_NULL;
- }
+ if (parse.abc_state != ABC_S_TUNE)
return 0;
- }
+ /* music */
flags = 0;
-
- if (abc_vers <= (2 << 16))
+ if (parse.abc_vers <= (2 << 16))
lyric_started = 0;
deco_start = deco_cont = NULL;
slur = 0;
@@ -2253,7 +1979,7 @@
last_note_sav = curvoice->last_note;
curvoice->last_note = NULL;
memcpy(&dc_sav, &dc, sizeof dc);
- dc.n = dc.h = dc.s = 0;
+ dc.n = 0;
flags_sav = flags;
flags = ABC_F_GRACE;
if (*p == '/') {
@@ -2264,7 +1990,9 @@
case CHAR_GR_EN: /* '}' */
if (!(flags & ABC_F_GRACE))
goto bad_char;
- t->last_sym->flags |= ABC_F_GR_END;
+ parse.last_sym->flags |= ABC_F_GR_END;
+ if (dc.n != 0)
+ syntax("Decoration ignored", p);
curvoice->last_note = last_note_sav;
memcpy(&dc, &dc_sav, sizeof dc);
flags = flags_sav;
@@ -2273,39 +2001,36 @@
if (p[-1] == '!'
&& char_tb['\n'] == CHAR_LINEBREAK
&& check_nl(p)) {
- s = abc_new(t, NULL, NULL); /* abc2win EOL */
- s->type = ABC_T_EOLN;
+ s = abc_new(ABC_T_EOLN, NULL); /* abc2win EOL */
s->u.eoln.type = 2;
break;
}
/* fall thru */
case CHAR_DECO:
if (p[-1] == '.') {
- if (*p == '(' || *p == '-' || *p == ')')
- break;
- if (*p == '|') {
- p = parse_bar(t, p + 1);
- t->last_sym->u.bar.dotted = 1;
+ if (*p == '(' || *p == '-') {
+ dot = p;
break;
}
+// if (*p == '|') {
+// p = parse_bar(p + 1);
+// parse.last_sym->u.bar.dotted = 1;
+// break;
+// }
}
- p = parse_deco(p - 1, &dc);
- dc.h = dc.s = dc.n;
+ p = parse_deco(p - 1, &dc, -1);
break;
case CHAR_LINEBREAK:
- s = abc_new(t, NULL, NULL);
- s->type = ABC_T_EOLN;
+ s = abc_new(ABC_T_EOLN, NULL);
// s->u.eoln.type = 0;
break;
- case CHAR_ACC:
case CHAR_NOTE:
- case CHAR_REST:
- p = parse_note(t, p - 1, flags);
+ p = parse_note(p - 1, flags);
flags &= ABC_F_GRACE;
- t->last_sym->u.note.slur_st = slur;
+ parse.last_sym->u.note.slur_st = slur;
slur = 0;
- if (t->last_sym->u.note.lens[0] > 0) /* if not space */
- curvoice->last_note = t->last_sym;
+ if (parse.last_sym->u.note.notes[0].len > 0) /* if not space */
+ curvoice->last_note = parse.last_sym;
break;
case CHAR_SLASH: /* '/' */
if (flags & ABC_F_GRACE)
@@ -2315,8 +2040,7 @@
q++;
if (char_tb[(unsigned char) *q] != CHAR_BAR)
goto bad_char;
- s = abc_new(t, NULL, NULL);
- s->type = ABC_T_MREP;
+ s = abc_new(ABC_T_MREP, NULL);
s->u.bar.type = 0;
s->u.bar.len = q - p + 1;
syntax("Non standard measure repeat syntax", p - 1);
@@ -2333,19 +2057,19 @@
|| *p == ' ') {
if (flags & ABC_F_GRACE)
goto bad_char;
- p = parse_bar(t, p);
+ p = parse_bar(p);
break;
}
if (p[1] != ':') {
- p = parse_note(t, p - 1, flags); /* chord */
+ p = parse_note(p - 1, flags); /* chord */
flags &= ABC_F_GRACE;
- t->last_sym->u.note.slur_st = slur;
+ parse.last_sym->u.note.slur_st = slur;
slur = 0;
- curvoice->last_note = t->last_sym;
+ curvoice->last_note = parse.last_sym;
break;
}
- /* embedded header */
+ /* embedded information field */
#if 0
/*fixme:OK for [I:staff n], ?? for other headers*/
if (flags & ABC_F_GRACE)
@@ -2366,7 +2090,7 @@
} else {
*p = '\0';
}
- parse_info(t, q, NULL);
+ parse_info(q);
*p = c;
if (c != '\0')
p++;
@@ -2374,17 +2098,13 @@
case CHAR_BAR: /* '|', ':' or ']' */
if (flags & ABC_F_GRACE)
goto bad_char;
- p = parse_bar(t, p);
+ p = parse_bar(p);
break;
case CHAR_OPAR: /* '(' */
- if (isdigit((unsigned char) *p)) {
+ if (*p > '0' && *p <= '9') {
int pplet, qplet, rplet;
pplet = strtol(p, &q, 10);
- if (pplet <= 1) {
- syntax("Invalid 'p' in tuplet", p);
- pplet = 0;
- }
p = q;
if ((unsigned) pplet < sizeof qtb / sizeof qtb[0])
qplet = qtb[pplet];
@@ -2405,16 +2125,17 @@
}
}
}
- if (pplet == 0)
- break;
if (rplet < 1) {
syntax("Invalid 'r' in tuplet", p);
break;
}
+ if (pplet >= 128 || qplet >= 128 || rplet >= 128) {
+ syntax("Invalid 'p:q:r' in tuplet", p);
+ break;
+ }
if (qplet == 0)
qplet = meter % 3 == 0 ? 3 : 2;
- s = abc_new(t, NULL, NULL);
- s->type = ABC_T_TUPLET;
+ s = abc_new(ABC_T_TUPLET, NULL);
s->u.tuplet.p_plet = pplet;
s->u.tuplet.q_plet = qplet;
s->u.tuplet.r_plet = rplet;
@@ -2429,15 +2150,14 @@
syntax("Nested voice overlay", p - 1);
break;
}
- s = abc_new(t, NULL, NULL);
- s->type = ABC_T_V_OVER;
+ s = abc_new(ABC_T_V_OVER, NULL);
s->u.v_over.type = V_OVER_S;
s->u.v_over.voice = curvoice - voice_tb;
vover = -1; /* multi-bars */
break;
}
- slur <<= 3;
- if (p[-2] == '.' && dc.n == 0)
+ slur <<= 4;
+ if (p == dot + 1 && dc.n == 0)
slur |= SL_DOTTED;
switch (*p) {
case '\'':
@@ -2454,14 +2174,14 @@
}
break;
case CHAR_CPAR: /* ')' */
- switch (t->last_sym->type) {
+ switch (parse.last_sym->abc_type) {
case ABC_T_NOTE:
case ABC_T_REST:
break;
default:
goto bad_char;
}
- t->last_sym->u.note.slur_end++;
+ parse.last_sym->u.note.slur_end++;
break;
case CHAR_VOV: /* '&' */
if (flags & ABC_F_GRACE)
@@ -2472,8 +2192,7 @@
syntax("Bad start of voice overlay", p);
break;
}
- s = abc_new(t, NULL, NULL);
- s->type = ABC_T_V_OVER;
+ s = abc_new(ABC_T_V_OVER, NULL);
/*s->u.v_over.type = V_OVER_V; */
vover_new();
s->u.v_over.voice = curvoice - voice_tb;
@@ -2483,8 +2202,7 @@
}
p++;
vover = 0;
- s = abc_new(t, NULL, NULL);
- s->type = ABC_T_V_OVER;
+ s = abc_new(ABC_T_V_OVER, NULL);
s->u.v_over.type = V_OVER_E;
s->u.v_over.voice = curvoice->mvoice;
curvoice->last_note = NULL; /* ?? */
@@ -2497,9 +2215,9 @@
int tie_pos;
if (!curvoice->last_note
- || curvoice->last_note->type != ABC_T_NOTE)
+ || curvoice->last_note->abc_type != ABC_T_NOTE)
goto bad_char;
- if (p[-2] == '.' && dc.n == 0)
+ if (p == dot + 1 && dc.n == 0)
tie_pos = SL_DOTTED;
else
tie_pos = 0;
@@ -2516,10 +2234,10 @@
tie_pos += SL_AUTO;
break;
}
- for (i = 0; i <= curvoice->last_note->u.note.nhd; i++) {
- if (curvoice->last_note->u.note.ti1[i] == 0)
- curvoice->last_note->u.note.ti1[i] = tie_pos;
- else if (curvoice->last_note->u.note.nhd == 0)
+ for (i = 0; i <= curvoice->last_note->nhd; i++) {
+ if (curvoice->last_note->u.note.notes[i].ti1 == 0)
+ curvoice->last_note->u.note.notes[i].ti1 = tie_pos;
+ else if (curvoice->last_note->nhd == 0)
syntax("Too many ties", p);
}
break;
@@ -2538,7 +2256,7 @@
}
if (p[-1] == '<')
i = -i;
- broken_rhythm(&curvoice->last_note->u.note, i);
+ broken_rhythm(curvoice->last_note, i);
curvoice->last_note->u.note.brhythm = i;
break;
case CHAR_IGN: /* '*' & '`' */
@@ -2563,37 +2281,33 @@
}
/* add eoln */
- s = abc_new(t, NULL, NULL);
- s->type = ABC_T_EOLN;
+ s = abc_new(ABC_T_EOLN, NULL);
if (flags & ABC_F_SPACE)
s->flags |= ABC_F_SPACE;
if (p[-1] == '\\'
|| char_tb['\n'] != CHAR_LINEBREAK)
s->u.eoln.type = 1; /* no break */
+
return 0;
}
/* -- parse a note or a rest -- */
-static char *parse_note(struct abctune *t,
- char *p,
+static char *parse_note(char *p,
int flags)
{
- struct abcsym *s;
+ struct SYMBOL *s;
char *q;
- int pit, len, acc, nostem, chord, j, m;
+ int pit, len, acc, nostem, chord, j, m, n;
if (flags & ABC_F_GRACE) { /* in a grace note sequence */
- s = abc_new(t, NULL, NULL);
+ s = abc_new(ABC_T_NOTE, NULL);
} else {
- s = abc_new(t, gchord, NULL);
- if (gchord) {
- if (free_f)
- free_f(gchord);
+ s = abc_new(ABC_T_NOTE, gchord);
+ if (gchord)
gchord = NULL;
- }
}
- s->type = ABC_T_NOTE;
s->flags |= flags;
+ s->u.note.notes[0].color = -1;
if (!lyric_started) {
lyric_started = 1;
@@ -2604,14 +2318,14 @@
if (!deco_start)
deco_start = s;
}
+ chord = 0;
/* rest */
switch (*p) {
case 'X':
+ s->flags |= ABC_F_INVIS;
case 'Z': /* multi-rest */
- s->type = ABC_T_MREST;
- if (*p == 'X')
- s->flags |= ABC_F_INVIS;
+ s->abc_type = ABC_T_MREST;
p++;
len = 1;
if (isdigit((unsigned char) *p)) {
@@ -2626,88 +2340,81 @@
s->u.bar.len = len;
goto add_deco;
case 'y': /* space (BarFly) */
- s->type = ABC_T_REST;
+ s->abc_type = ABC_T_REST;
s->flags |= ABC_F_INVIS;
p++;
- if (isdigit((unsigned char) *p)) { /* number of points */
- s->u.note.lens[1] = strtol(p, &q, 10);
+ if (isdigit((unsigned char) *p) /* number of points */
+ || *p == '-') { /* accept negative offset... */
+ s->u.note.notes[0].shhd = strtol(p, &q, 10);
p = q;
} else {
- s->u.note.lens[1] = -1;
+ s->u.note.notes[0].shhd = 10; // default
}
goto add_deco;
case 'x': /* invisible rest */
s->flags |= ABC_F_INVIS;
/* fall thru */
case 'z':
- s->type = ABC_T_REST;
- p = parse_len(p + 1, &len);
- s->u.note.lens[0] = len * ulen / BASE_LEN;
+ s->abc_type = ABC_T_REST;
+ p = parse_len(p + 1, ulen, &len);
+ s->u.note.notes[0].len = len;
goto do_brhythm;
- }
-
- chord = 0;
- q = p;
- if (*p == '[') { /* '[..]' = chord */
+ case '[': /* '[..]' = chord */
chord = 1;
p++;
+ break;
}
+ q = p;
+
/* get pitch, length and possible accidental */
m = 0;
nostem = 0;
for (;;) {
- int tmp;
-
if (chord) {
if (m >= MAXHD) {
syntax("Too many notes in chord", p);
m--;
}
- tmp = 0;
+ n = 0;
if (*p == '.') {
- tmp = SL_DOTTED;
+ n = SL_DOTTED;
p++;
}
if (*p == '(') {
p++;
switch (*p) {
case '\'':
- tmp += SL_ABOVE;
+ n += SL_ABOVE;
p++;
break;
case ',':
- tmp += SL_BELOW;
+ n += SL_BELOW;
p++;
break;
default:
- tmp += SL_AUTO;
+ n += SL_AUTO;
break;
}
- s->u.note.sl1[m] = (s->u.note.sl1[m] << 3)
- + tmp;
+ s->u.note.notes[m].sl1 = (s->u.note.notes[m].sl1 << 3)
+ + n;
}
}
- tmp = dc.n;
- p = parse_deco(p, &dc); /* note head decorations */
- if (dc.n != tmp) {
- if (dc.n - tmp >= 8) {
- syntax("Too many decorations on this head", p);
- tmp = dc.n - 7;
- }
- s->u.note.decs[m] = (tmp << 3) + dc.n - tmp;
- dc.s = dc.n;
- }
- p = parse_basic_note(p, &pit, &len, &acc, &tmp);
- if (!(flags & ABC_F_GRACE))
- len = len * ulen / BASE_LEN;
- else
- len /= 8; /* for grace note alone */
-
- s->u.note.pits[m] = pit;
- s->u.note.lens[m] = len;
- s->u.note.accs[m] = acc;
- nostem |= tmp;
+ p = parse_deco(p, &dc, m); /* note head decorations */
+ p = parse_acc_pit(p, &pit, &acc);
+ if (*p == '0') {
+ nostem = 1;
+ p++;
+ }
+ p = parse_len(p, (flags & ABC_F_GRACE) ?
+ BASE_LEN / 8 : // for grace note alone
+ ulen,
+ &len);
+ s->u.note.notes[m].pit = pit;
+ s->pits[m] = pit;
+ s->u.note.notes[m].len = len;
+ s->u.note.notes[m].acc = acc;
+ s->u.note.notes[m].color = -1;
if (chord) {
for (;;) {
@@ -2719,19 +2426,19 @@
if (*p == '-') {
switch (p[1]) {
case '\'':
- s->u.note.ti1[m] = SL_ABOVE;
+ s->u.note.notes[m].ti1 = SL_ABOVE;
p++;
break;
case ',':
- s->u.note.ti1[m] = SL_BELOW;
+ s->u.note.notes[m].ti1 = SL_BELOW;
p++;
break;
default:
- s->u.note.ti1[m] = SL_AUTO;
+ s->u.note.notes[m].ti1 = SL_AUTO;
break;
}
} else if (*p == ')') {
- s->u.note.sl2[m]++;
+ s->u.note.notes[m].sl2++;
} else {
break;
}
@@ -2746,15 +2453,14 @@
if (*p == ']') {
p++;
if (*p == '0') {
- nostem |= 1;
+ nostem = 1;
p++;
}
if (*p == '/' || isdigit((unsigned char) *p)) {
- p = parse_len(p, &len);
- s->u.note.chlen = len;
+ p = parse_len(p, ulen, &len);
for (j = 0; j < m; j++) {
- tmp = len * s->u.note.lens[j];
- s->u.note.lens[j] = tmp / BASE_LEN;
+ s->u.note.notes[j].len =
+ len * s->u.note.notes[j].len / ulen;
}
}
break;
@@ -2771,55 +2477,53 @@
goto err;
s->u.note.microscale = microscale;
- s->u.note.nhd = m - 1;
+ s->nhd = m - 1;
+
do_brhythm:
if (curvoice->last_note
&& curvoice->last_note->u.note.brhythm != 0)
- broken_rhythm(&s->u.note,
- -curvoice->last_note->u.note.brhythm);
+ broken_rhythm(s, -curvoice->last_note->u.note.brhythm);
add_deco:
if (dc.n > 0) {
- memcpy(s->type != ABC_T_MREST ? &s->u.note.dc
+ memcpy(s->abc_type != ABC_T_MREST ? &s->u.note.dc
: &s->u.bar.dc,
&dc, sizeof dc);
- dc.n = dc.h = dc.s = 0;
+ dc.n = 0;
}
+
/* forbid rests in grace note sequences */
- if (s->type != ABC_T_NOTE && (flags & ABC_F_GRACE)) {
+ if (s->abc_type != ABC_T_NOTE && (flags & ABC_F_GRACE)) {
syntax("Not a note in grace note sequence", p);
goto err;
}
return p;
err:
- if ((t->last_sym = s->prev) == NULL) {
- t->first_sym = NULL;
+ if ((parse.last_sym = s->abc_prev) == NULL) {
+ parse.first_sym = NULL;
} else {
- s->prev->next = NULL;
- s->prev->flags |= (s->flags & ABC_F_ERROR);
+ s->abc_prev->abc_next = NULL;
+ s->abc_prev->flags |= (s->flags & ABC_F_ERROR);
}
return p;
}
/* -- parse an information field -- */
/* return 2 on start of new tune */
-static int parse_info(struct abctune *t,
- char *p,
- char *comment)
+static int parse_info(char *p)
{
- struct abcsym *s;
+ struct SYMBOL *s;
char info_type = *p;
char *error_txt = NULL;
- s = abc_new(t, p, comment);
- s->type = ABC_T_INFO;
+ s = abc_new(ABC_T_INFO, p);
p += 2;
switch (info_type) {
case 'd':
case 's':
- if (abc_state == ABC_S_GLOBAL)
+ if (parse.abc_state == ABC_S_GLOBAL)
break;
if (!deco_start) {
error_txt = "Erroneous 'd:'/'s:'";
@@ -2828,13 +2532,13 @@
error_txt = parse_decoline(p);
break;
case 'K':
- if (abc_state == ABC_S_GLOBAL)
+ if (parse.abc_state == ABC_S_GLOBAL)
break;
parse_key(p, s);
- if (abc_state == ABC_S_HEAD) {
+ if (parse.abc_state == ABC_S_HEAD) {
int i;
- abc_state = ABC_S_TUNE;
+ parse.abc_state = ABC_S_TUNE;
if (ulen == 0)
ulen = BASE_LEN / 8;
for (i = MAXVOICE; --i >= 0; )
@@ -2857,17 +2561,16 @@
error_txt = get_user(p, s);
break;
case 'V':
- if (abc_state == ABC_S_GLOBAL)
+ if (parse.abc_state == ABC_S_GLOBAL)
break;
error_txt = parse_voice(p, s);
break;
case 'X':
memset(voice_tb, 0, sizeof voice_tb);
nvoice = 0;
- curvoice = &voice_tb[0];
- abc_state = ABC_S_HEAD;
- if (level_f)
- level_f(1);
+ curvoice = voice_tb;
+ parse.abc_state = ABC_S_HEAD;
+ lvlarena(1);
return 2;
}
if (error_txt)
diff -Nru abcm2ps-7.8.9/abcparse.h abcm2ps-8.14.2/abcparse.h
--- abcm2ps-7.8.9/abcparse.h 2014-03-26 07:49:34.000000000 +0000
+++ abcm2ps-8.14.2/abcparse.h 1970-01-01 00:00:00.000000000 +0000
@@ -1,238 +0,0 @@
-/*++
- * Declarations for abcparse.c.
- *
- *-*/
-
-#define MAXVOICE 32 /* max number of voices */
-
-#define MAXHD 8 /* max heads in a chord */
-#define MAXDC 45 /* max decorations per note/chord/bar */
-#define MAXMICRO 32 /* max microtone values (5 bits in accs[]) */
-
-#define BASE_LEN 1536 /* basic note length (semibreve or whole note - same as MIDI) */
-
-#define VOICE_ID_SZ 16 /* max size of the voice identifiers */
-
-/* accidentals */
-enum accidentals {
- A_NULL, /* none */
- A_SH, /* sharp */
- A_NT, /* natural */
- A_FT, /* flat */
- A_DS, /* double sharp */
- A_DF /* double flat */
-};
-
-/* bar types - 4 bits per symbol */
-#define B_BAR 1 /* | */
-#define B_OBRA 2 /* [ */
-#define B_CBRA 3 /* ] */
-#define B_COL 4 /* : */
-
-/* slur/tie types (3 bits) */
-#define SL_ABOVE 0x01
-#define SL_BELOW 0x02
-#define SL_AUTO 0x03
-#define SL_DOTTED 0x04 /* (modifier bit) */
-
-/* note structure */
-struct deco { /* decorations */
- char n; /* whole number of decorations */
- char h; /* start of head decorations */
- char s; /* start of decorations from s: (d:) */
- unsigned char t[MAXDC]; /* decoration type */
-};
-
-struct note { /* note or rest */
- signed char pits[MAXHD]; /* pitches */
- short lens[MAXHD]; /* note lengths (# pts in [1] if space) */
- unsigned char accs[MAXHD]; /* code for accidentals & index in micro_tb */
- unsigned char sl1[MAXHD]; /* slur start per head */
- char sl2[MAXHD]; /* number of slur end per head */
- char ti1[MAXHD]; /* flag to start tie here */
- unsigned char decs[MAXHD]; /* head decorations (index: 5 bits, len: 3 bits) */
- short chlen; /* chord length */
- char nhd; /* number of notes in chord - 1 */
- unsigned char slur_st; /* slurs starting here (2 bits array) */
- char slur_end; /* number of slurs ending here */
- signed char brhythm; /* broken rhythm */
- unsigned char microscale; /* microtone denominator - 1 */
- struct deco dc; /* decorations */
-};
-
-/* symbol definition */
-struct abctune;
-struct abcsym {
- struct abctune *tune; /* tune */
- struct abcsym *next, *prev; /* next / previous symbol */
- char type; /* symbol type */
-#define ABC_T_NULL 0
-#define ABC_T_INFO 1 /* (text[0] gives the info type) */
-#define ABC_T_PSCOM 2
-#define ABC_T_CLEF 3
-#define ABC_T_NOTE 4
-#define ABC_T_REST 5
-#define ABC_T_BAR 6
-#define ABC_T_EOLN 7
-#define ABC_T_MREST 8 /* multi-measure rest */
-#define ABC_T_MREP 9 /* measure repeat */
-#define ABC_T_V_OVER 10 /* voice overlay */
-#define ABC_T_TUPLET 11
- char state; /* symbol state in file/tune */
-#define ABC_S_GLOBAL 0 /* global */
-#define ABC_S_HEAD 1 /* in header (after X:) */
-#define ABC_S_TUNE 2 /* in tune (after K:) */
- unsigned short flags;
-#define ABC_F_ERROR 0x0001 /* error around this symbol */
-#define ABC_F_INVIS 0x0002 /* invisible symbol */
-#define ABC_F_SPACE 0x0004 /* space before a note */
-#define ABC_F_STEMLESS 0x0008 /* note with no stem */
-#define ABC_F_LYRIC_START 0x0010 /* may start a lyric here */
-#define ABC_F_GRACE 0x0020 /* grace note */
-#define ABC_F_GR_END 0x0040 /* end of grace note sequence */
-#define ABC_F_SAPPO 0x0080 /* short appoggiatura */
- unsigned short colnum; /* ABC source column number */
- int linenum; /* ABC source line number */
- char *fn; /* ABC source file name */
- char *text; /* main text (INFO, PSCOM),
- * guitar chord (NOTE, REST, BAR) */
- char *comment; /* comment part (when keep_comment) */
- union { /* type dependent part */
- struct key_s { /* K: info */
- signed char sf; /* sharp (> 0) flats (< 0) */
- char empty; /* clef alone if 1, 'none' if 2 */
- char exp; /* exp (1) or mod (0) */
- char mode; /* mode */
-/* 0: Ionian, 1: Dorian, 2: Phrygian, 3: Lydian, 4: Mixolydian
- * 5: Aeolian, 6: Locrian, 7: major, 8:minor, 9: HP, 10: Hp */
-#define MAJOR 7
-#define MINOR 8
-#define BAGPIPE 9 /* bagpipe when >= 8 */
- signed char nacc; /* number of explicit accidentals */
- /* (-1) if no accidental */
- signed char octave; /* 'octave=' */
-#define NO_OCTAVE 10 /* no 'octave=' */
- unsigned char microscale; /* microtone denominator - 1 */
- signed char pits[8];
- unsigned char accs[8];
- } key;
- struct { /* L: info */
- int base_length; /* basic note length */
- } length;
- struct meter_s { /* M: info */
- short wmeasure; /* duration of a measure */
- unsigned char nmeter; /* number of meter elements */
- char expdur; /* explicit measure duration */
-#define MAX_MEASURE 6
- struct {
- char top[8]; /* top value */
- char bot[2]; /* bottom value */
- } meter[MAX_MEASURE];
- } meter;
- struct { /* Q: info */
- char *str1; /* string before */
- short length[4]; /* up to 4 note lengths */
- char *value; /* tempo value */
- char *str2; /* string after */
- } tempo;
- struct { /* V: info */
- char id[VOICE_ID_SZ]; /* voice ID */
- char *fname; /* full name */
- char *nname; /* nick name */
- float scale; /* != 0 when change */
- unsigned char voice; /* voice number */
- signed char octave; /* 'octave=' - same as in K: */
- char merge; /* merge with previous voice */
- signed char stem; /* have stems up or down (2 = auto) */
- signed char gstem; /* have grace stems up or down (2 = auto) */
- signed char dyn; /* have dynamic marks above or below the staff */
- signed char lyrics; /* have lyrics above or below the staff */
- signed char gchord; /* have gchord above or below the staff */
- } voice;
- struct { /* bar, mrest or mrep */
- int type;
- char repeat_bar;
- char len; /* len if mrest or mrep */
- char dotted;
- struct deco dc; /* decorations */
- } bar;
- struct clef_s { /* clef (and staff!) */
- char *name; /* PS drawing function */
- float staffscale; /* != 0 when change */
- signed char stafflines; /* >= 0 when change */
- signed char type; /* no clef if < 0 */
-#define TREBLE 0
-#define ALTO 1
-#define BASS 2
-#define PERC 3
- char line;
- signed char octave;
- signed char transpose;
- char invis;
- char check_pitch; /* check if old abc2ps transposition */
- } clef;
- struct note note; /* note, rest */
- struct { /* user defined accent */
- unsigned char symbol;
- unsigned char value;
- } user;
- struct {
- char type; /* 0: end of line
- * 1: continuation ('\')
- * 2: line break ('!') */
- } eoln;
- struct { /* voice overlay */
- char type;
-#define V_OVER_V 0 /* & */
-#define V_OVER_S 1 /* (& */
-#define V_OVER_E 2 /* &) */
- unsigned char voice;
- } v_over;
- struct { /* tuplet */
- char p_plet, q_plet, r_plet;
- } tuplet;
- } u;
-};
-
-/* tune definition */
-struct abctune {
- struct abctune *next; /* next tune */
- struct abcsym *first_sym; /* first symbol */
- struct abcsym *last_sym; /* last symbol */
- int abc_vers; /* ABC version = (H << 16) + (M << 8) + L */
- void *client_data; /* client data */
- unsigned short micro_tb[MAXMICRO]; /* microtone values [ (n-1) | (d-1) ] */
-};
-
-#ifdef WIN32
-#define strcasecmp stricmp
-#define strncasecmp strnicmp
-#endif
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-extern char *deco_tb[];
-extern int severity;
-
-void abc_delete(struct abcsym *as);
-void abc_free(struct abctune *first_tune);
-void abc_init(void *alloc_f_api(int size),
- void free_f_api(void *ptr),
- void level_f_api(int level),
- int client_sz_api,
- int keep_comment_api);
-void abc_insert(char *file_api,
- struct abcsym *s);
-struct abcsym *abc_new(struct abctune *t,
- char *p,
- char *comment);
-struct abctune *abc_parse(char *file_api);
-char *get_str(char *d,
- char *s,
- int maxlen);
-char *parse_deco(char *p,
- struct deco *deco);
-#if defined(__cplusplus)
-}
-#endif
diff -Nru abcm2ps-7.8.9/accordion.abc abcm2ps-8.14.2/accordion.abc
--- abcm2ps-7.8.9/accordion.abc 2011-11-03 18:22:22.000000000 +0000
+++ abcm2ps-8.14.2/accordion.abc 2018-12-18 15:18:26.000000000 +0000
@@ -45,7 +45,7 @@
M:4/4
K:Am
%%tablature 70 accordh accordn accordb
- "A"A2 cA "F" aAce | "G"dGBd "C"e4 | "F"fedc "G"B2 AB |1 "F"cABc "E"B4 :|2 "F"cABc "A"A4 :|\
+ "A"A2 cA "F" aAce | "G"dGBd "C"e4 | "F"fedc "G"B2 AB |1 "F"cABc "E"B4 :|2 "F"cABc "A"A4 :|
w: * * * * * * * 8 6 7 8 7' * * * * * * * * * * * 7 * * * * *
w: 7 8 7 11 7 8 9 * * * * * 8' 9 7' 8 6' 7 6' 8 7 6' 8 * 8 7 6' 8 7
"A"A2 GF "E"E3 B | "E"c2 d2 "C"e4 | "F"fedc "G"B2 AB |1 "F"cABc "E"B4 :|2 "F"cABc "A"A4 :|
diff -Nru abcm2ps-7.8.9/bravura.abc abcm2ps-8.14.2/bravura.abc
--- abcm2ps-7.8.9/bravura.abc 1970-01-01 00:00:00.000000000 +0000
+++ abcm2ps-8.14.2/bravura.abc 2018-12-18 15:18:26.000000000 +0000
@@ -0,0 +1,56 @@
+% example of musical symbols by Bravura
+
+% --- definitions for SVG output ---
+%%beginsvg
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+%%endsvg
+
+% --- definitions for PostScript output ---
+%%beginps nosvg
+/brace{/Bravura 24 selectfont
+ gsave
+ T -7.5 0 M -.042 mul 3 exch scale
+ /uniE000 glyphshow
+ grestore}!
+/tclef{/Bravura 24 selectfont M -8 6 RM/uniE050 glyphshow}!
+/cclef{/Bravura 24 selectfont M -8 12 RM/uniE05C glyphshow}!
+/bclef{/Bravura 24 selectfont M -8 18 RM/uniE062 glyphshow}!
+/csig{/Bravura 24 selectfont M -5 12 RM/uniE08A glyphshow}!
+/ft0{/Bravura 24 selectfont M -2 0 RM/uniE260 glyphshow}!
+/nt0{/Bravura 24 selectfont M -2 0 RM/uniE261 glyphshow}!
+/sh0{/Bravura 24 selectfont M -2 0 RM/uniE262 glyphshow}!
+/dsh0{/Bravura 24 selectfont M -2 0 RM/uniE263 glyphshow}!
+/dft0{/Bravura 24 selectfont M -3 0 RM/uniE264 glyphshow}!
+/turn{/Bravura 24 selectfont M -4 0 RM/uniE567 glyphshow}!
+%%endps
diff -Nru abcm2ps-7.8.9/buffer.c abcm2ps-8.14.2/buffer.c
--- abcm2ps-7.8.9/buffer.c 2014-07-04 18:10:30.000000000 +0000
+++ abcm2ps-8.14.2/buffer.c 2018-12-18 15:18:26.000000000 +0000
@@ -3,22 +3,13 @@
*
* This file is part of abcm2ps.
*
- * Copyright (C) 1998-2014 Jean-François Moine
+ * Copyright (C) 1998-2017 Jean-François Moine
* Adapted from abc2ps, Copyright (C) 1996,1997 Michael Methfessel
*
* This program 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 2 of the License, or
* (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*/
#include
@@ -26,12 +17,9 @@
#include
#include
-#ifdef WIN32
-#define snprintf _snprintf
-#endif
-
-#include "abc2ps.h"
+#include "abcm2ps.h"
+#define PPI_96_72 0.75 // convert page format to 72 PPI
#define BUFFLN 80 /* max number of lines in output buffer */
static int ln_num; /* number of lines in buffer */
@@ -43,11 +31,12 @@
static float cur_lmarg = 0; /* current left margin */
static float min_lmarg, max_rmarg; /* margins for -E/-g */
static float cur_scale = 1.0; /* current scale */
-static float maxy; /* remaining vertical space in page */
+static float maxy; /* usable vertical space in page */
+static float remy; /* remaining vertical space in page */
static float bposy; /* current position in buffered data */
static int nepsf; /* counter for -E/-g output files */
static int nbpages; /* number of pages in the output file */
-static int outbufsz; /* size of outbuf */
+ int outbufsz; /* size of outbuf */
static char outfnam[FILENAME_MAX]; /* internal file name for open/close */
static struct FORMAT *p_fmt; /* current format while treating a new page */
@@ -57,6 +46,11 @@
char *outbuf; /* output buffer.. should hold one tune */
char *mbf; /* where to a2b() */
int use_buffer; /* 1 if lines are being accumulated */
+int (*output)(FILE *out, const char *fmt, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 2, 3)))
+#endif
+ ;
/* -- cut off extension on a file identifier -- */
static void cutext(char *fid)
@@ -70,7 +64,7 @@
}
/* -- open the output file -- */
-static void open_fout(void)
+void open_fout(void)
{
int i;
char fnm[FILENAME_MAX];
@@ -78,29 +72,20 @@
strcpy(fnm, outfn);
i = strlen(fnm) - 1;
if (i < 0) {
- strcpy(fnm, svg ? "Out.xhtml" : OUTPUTFILE);
-#if 1
+ strcpy(fnm, svg || epsf > 1 ? "Out.xhtml" : OUTPUTFILE);
} else if (i != 0 || fnm[0] != '-') {
-#else
- } else if (i == 0 && fnm[0] == '-') {
- if (svg == 1) {
- error(1, 0, "Cannot use stdout with '-v' - abort");
- exit(EXIT_FAILURE);
- }
- } else {
-#endif
- if (fnm[i] == '=') {
+ if (fnm[i] == '=' && in_fname) {
char *p;
- if ((p = strrchr(in_fname, DIRSEP)) == 0)
+ if ((p = strrchr(in_fname, DIRSEP)) == NULL)
p = in_fname;
else
p++;
-/*fixme: should check if there is a DIRSEP at the end of fnm*/
strcpy(&fnm[i], p);
- strext(fnm, svg ? "xhtml" : "ps");
+ strext(fnm, svg || epsf > 1 ? "xhtml" : "ps");
} else if (fnm[i] == DIRSEP) {
- strcpy(&fnm[i + 1], OUTPUTFILE);
+ strcpy(&fnm[i + 1],
+ svg || epsf > 1 ? "Out.xhtml" : OUTPUTFILE);
}
#if 0
/*fixme: fnm may be a directory*/
@@ -153,23 +138,23 @@
{
time_t ltime;
unsigned i;
- char version[32];
+ char version[] = "/creator [(abcm2ps) " VERSION "] def";
if (epsf) {
cur_lmarg = min_lmarg - 10;
fprintf(fout, "%%!PS-Adobe-2.0 EPSF-2.0\n"
"%%%%BoundingBox: 0 0 %.0f %.0f\n",
- (p_fmt->landscape ? p_fmt->pageheight : p_fmt->pagewidth)
- - cur_lmarg - max_rmarg + 10,
- -bposy);
+ ((p_fmt->landscape ? p_fmt->pageheight : p_fmt->pagewidth)
+ - cur_lmarg - max_rmarg + 10) * PPI_96_72,
+ -bposy * PPI_96_72);
marg_init();
} else {
if (!fout)
open_fout();
fprintf(fout, "%%!PS-Adobe-2.0\n");
fprintf(fout, "%%%%BoundingBox: 0 0 %.0f %.0f\n",
- p_fmt->pagewidth,
- p_fmt->pageheight);
+ p_fmt->pagewidth * PPI_96_72,
+ p_fmt->pageheight * PPI_96_72);
}
fprintf(fout, "%%%%Title: %s\n", str);
time(<ime);
@@ -208,7 +193,6 @@
fprintf(fout, "\n\n");
if (epsf)
fprintf(fout, "save\n");
- strcpy(version, "/creator [(abcm2ps) " VERSION "] def");
for (i = 0; i < strlen(version); i++) {
if (version[i] == '.')
version[i] = ' ';
@@ -226,16 +210,22 @@
"/SLW/setlinewidth load def\n"
"/defl 0 def\n" /* decoration flags - see deco.c for values */
"/dlw{0.7 SLW}!\n"
-
"%s\n", version);
define_symbols();
output = fprintf;
user_ps_write();
define_fonts();
- if (!epsf)
+ if (!epsf) {
fprintf(fout, "/setpagedevice where{pop\n"
- " <>setpagedevice}if\n",
- p_fmt->pagewidth, p_fmt->pageheight);
+ " <pagewidth * PPI_96_72,
+ p_fmt->pageheight * PPI_96_72);
+ if (cfmt.gutter)
+ fprintf(fout,
+ "\n /BeginPage{1 and 0 eq{%.1f 0 T}{-%.1f 0 T}ifelse}bind\n ",
+ cfmt.gutter, cfmt.gutter);
+ fprintf(fout, ">>setpagedevice}if\n");
+ }
fprintf(fout, "%%%%EndSetup\n");
file_initialized = 1;
}
@@ -246,8 +236,8 @@
cur_lmarg = min_lmarg - 10;
output = svg_output;
#if 1 //fixme:test
- if (file_initialized)
- fprintf(stderr, "??? init_svg: file_initialized");
+ if (file_initialized > 0)
+ fprintf(stderr, "??? init_svg: file_initialized\n");
#endif
define_svg_symbols(str, nepsf,
(p_fmt->landscape ? p_fmt->pageheight : p_fmt->pagewidth)
@@ -267,11 +257,10 @@
goto out1;
m = ftell(fout);
if (epsf || svg == 1)
- fprintf(stderr, "Output written on %s (%ld bytes)\n",
+ printf("Output written on %s (%ld bytes)\n",
outfnam, m);
else
- fprintf(stderr,
- "Output written on %s (%d page%s, %d title%s, %ld bytes)\n",
+ printf("Output written on %s (%d page%s, %d title%s, %ld bytes)\n",
outfnam,
nbpages, nbpages == 1 ? "" : "s",
tunenum, tunenum == 1 ? "" : "s",
@@ -297,17 +286,25 @@
if (tunenum == 0)
error(0, NULL, "No tunes written to output file");
close_page();
- if (!svg) {
- fprintf(fout, "%%%%Trailer\n"
- "%%%%Pages: %d\n"
- "%%EOF\n", nbpages);
+ switch (svg) {
+ case 0: /* PS */
+ if (epsf == 0)
+ fprintf(fout, "%%%%Trailer\n"
+ "%%%%Pages: %d\n"
+ "%%EOF\n", nbpages);
close_fout();
- } else if (svg == 2) {
+ break;
+ case 2: /* -X */
fputs("