summaryrefslogtreecommitdiff
path: root/Build/source/texk/musixtnt/musixtnt-2015-02-09/msxlint.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/musixtnt/musixtnt-2015-02-09/msxlint.c')
-rw-r--r--Build/source/texk/musixtnt/musixtnt-2015-02-09/msxlint.c422
1 files changed, 422 insertions, 0 deletions
diff --git a/Build/source/texk/musixtnt/musixtnt-2015-02-09/msxlint.c b/Build/source/texk/musixtnt/musixtnt-2015-02-09/msxlint.c
new file mode 100644
index 00000000000..47a8bede0c4
--- /dev/null
+++ b/Build/source/texk/musixtnt/musixtnt-2015-02-09/msxlint.c
@@ -0,0 +1,422 @@
+char version[12] = "2015-02-09";
+
+/* Copyright (C) 2014-15 R. D. Tennent School of Computing,
+ * Queen's University, rdt@cs.queensu.ca
+ *
+ * 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,
+ * Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/* msxlint - detects incorrectly formatted notes lines
+ * in a MusiXTeX source file.
+ *
+ * Usage: msxlint [-v | --version | -h | --help]
+ * msxlint [-d | --debug] { infile[.tex] } ...
+ *
+ */
+
+
+# include "utils.h"
+
+PRIVATE int debug = 0;
+PRIVATE char infilename[LINE_LEN];
+PRIVATE char *infilename_n = infilename;
+
+PRIVATE FILE *infile;
+
+PRIVATE char line[LINE_LEN]; /* line of input */
+PRIVATE int lineno; /* line number */
+PRIVATE int ninstr; /* number of instruments */
+PRIVATE int staffs[12]; /* staffs[i] is the number of staffs
+ for instrument i */
+PRIVATE char terminator[8]; /* "\en" or "\enotes" or "" (either) */
+PRIVATE int nerrors; /* number of error messages */
+# define NERRORSMAX 10
+
+PRIVATE void
+checkc (char *s, char c)
+{ if (*s != c)
+ printf ("Expected %c but found %c in line %d:\n%s\n", c, *s, lineno, line);
+}
+
+PRIVATE void
+checkn (char *s)
+{ if (strpbrk (s, "0123456789") != s)
+ printf ("Expected digit but found %c in line %d:\n%s\n", *s, lineno, line);
+}
+
+PRIVATE void
+usage (void)
+{
+ puts ("Usage: msxlint [-v | --version | -h | --help]");
+ puts (" msxlint [-d | --debug] ... { infile[.tex] } ...");
+}
+
+PRIVATE void
+analyze_notes ( char **ln) {
+ int i,j;
+ int newlines = 0;
+ char *s; char *t;
+ s = strpbrk (*ln+1, "|&\\\n"); /* skip initial command */
+ while (true)
+ { /* look for \en */
+ t = strstr(s, "\\en");
+ if (t != NULL) break;
+ else
+ /* replace EOL by a blank and append another line of input */
+ { char new_line[LINE_LEN];
+ if (debug > 2) printf (" Reading additional line of input:\n");
+ if ( fgets (new_line, LINE_LEN, infile) == NULL)
+ error("Unexpected EOF.");
+ if ( (t = strchr (s, '\n')) == NULL )
+ error("Missing EOL.");
+ *t = ' ';
+ t++;
+ *t = '\0';
+ if (append (line, &t, new_line, LINE_LEN) >= LINE_LEN)
+ error ("Line too Long.");
+ if (debug > 2) printf (" %s\n", t+1);
+ newlines++;
+ }
+ }
+ for (i=1; i <= ninstr; i++)
+ {
+ for (j=1; j < staffs[i]; j++)
+ { s = strpbrk (s, "|&");
+ if (s == NULL || *s == '&' || s > t)
+ {
+ printf ("Too few staffs for instrument %d in notes on line %d:\n%s", i, lineno, line);
+ nerrors++;
+ *ln = t+3;
+ return;
+ }
+ checkc (s, '|'); s++;
+ }
+ if (i == ninstr) break;
+ s = strpbrk (s, "&|");
+ if (s == NULL || s > t)
+ {
+ printf ("Too few instruments in notes on line %d:\n%s", lineno, line);
+ nerrors++;
+ *ln = t+3;
+ return;
+ }
+ if (*s == '|')
+ {
+ printf ("Too many staffs for instrument %d in notes on line %d:\n%s", i, lineno, line);
+ nerrors++;
+ *ln = t+3;
+ return;
+ }
+ checkc (s, '&'); s++;
+ }
+ s = strpbrk (s, "|&");
+ if (s != NULL && s < t)
+ {
+ printf ("Too many fields in notes on line %d:\n%s", lineno, line);
+ nerrors++;
+ *ln = t+3;
+ return;
+ }
+ s = t; /* \en */
+ if (terminator[0] != '\0')
+ { if (!prefix (terminator, s) )
+ {
+ printf ("Expected %s at end of notes on line %d:\n%s", terminator, lineno, line);
+ nerrors++;
+ t = strchr(s, '\\');
+ if (t == NULL) t = *ln + strlen (*ln);
+ *ln = t;
+ return;
+ }
+ if ( terminator[3] == '\0' && prefix ("otes", s+3) )
+ {
+ printf ("Expected %s at end of notes on line %d:\n%s", terminator, lineno, line);
+ nerrors++;
+ t = strchr(s, '\\');
+ if (t == NULL) t = *ln + strlen (*ln);
+ *ln = t;
+ return;
+ }
+ }
+ lineno = lineno + newlines;
+ t = strchr(s+1, '\\');
+ if (t == NULL) t = *ln + strlen (*ln);
+ *ln = t;
+ return;
+}
+
+PRIVATE void
+process_command (char **ln)
+{ char *s, *t;
+ if ( prefix("\\instrumentnumber", *ln) )
+ {
+ if (debug > 1) printf ("%s\n", " Processing \\instrumentnumber");
+ s = strpbrk (*ln, "123456789");
+ if ( s == NULL ) error ("\\instrumentnumber command unreadable.");
+ ninstr = atoi (s);
+ t = strpbrk (*ln+1, "\\");
+ if (t == NULL)
+ { *ln = *ln + strlen (*ln); return; }
+ *ln = t;
+ }
+
+ if ( prefix("\\def\\nbinstrument", *ln) )
+ {
+ if (debug > 1) printf ("%s\n", " Processing \\def\\nbinstrument");
+ s = strpbrk (*ln, "123456789");
+ if ( s == NULL ) error ("\\def\\nbinstrument command unreadable.");
+ ninstr = atoi (s);
+ t = strpbrk (*ln+1, "\\");
+ if (t == NULL)
+ { *ln = *ln + strlen (*ln); return; }
+ *ln = t;
+ }
+
+ else if ( prefix("\\setstaffs", *ln) )
+ {
+ int n, p;
+ if (debug > 1) printf ("%s\n", " Processing \\setstaffs");
+ s = strpbrk (*ln, "123456789");
+ if ( s == NULL ) error ("\\setstaffs command unreadable.");
+ n = (int)(*s) - (int)('0'); /* instrument number */
+ s = strpbrk (s+1, "123456789");
+ if ( s == NULL ) error ("\\setstaffs command unreadable.");
+ p = (int)(*s) - (int)('0'); /* number of staffs */
+ staffs[n] = p;
+ t = strpbrk (*ln+1, "\\");
+ if (t == NULL)
+ { *ln = *ln + strlen (*ln); return; }
+ *ln = t;
+ }
+
+ else if ( prefix("\\def\\vnotes#1\\elemskip", *ln) )
+ {
+ if (debug > 1) printf ("%s\n", " Processing \\def\\vnotes");
+ s = *ln + 22; /* first parameter */
+ ninstr = 0;
+ while (true)
+ { ninstr++;
+ staffs[ninstr] = 1;
+ checkc (s, '#'); s++;
+ checkn (s); s++;
+ while (*s == '|')
+ { staffs[ninstr]++;
+ checkc (s, '|'); s++;
+ checkc (s, '#'); s++;
+ checkn (s); s++;
+ }
+ if (*s != '&') break;
+ checkc (s, '&'); s++;
+ }
+ t = &terminator[0];
+ while (*s != '{')
+ { *t = *s; s++; t++; }
+ *t = '\0';
+ *ln = strchr (*ln, '}') ;
+ (*ln)++;
+ }
+
+ else if ( prefix("\\TransformNotes", *ln) )
+ {
+ if (debug > 1) printf ("%s\n", " Processing \\TransformNotes");
+ s = *ln + 16; /* first parameter */
+ ninstr = 0;
+ while (true)
+ { ninstr++;
+ staffs[ninstr] = 1;
+ checkc (s, '#'); s++;
+ checkn (s); s++;
+ while (*s == '|')
+ { staffs[ninstr]++;
+ checkc (s, '|'); s++;
+ checkc (s, '#'); s++;
+ checkn (s); s++;
+ }
+ if (*s != '&') break;
+ checkc (s, '&'); s++;
+ }
+ t = &terminator[0];
+ terminator[0] = '\0';
+ append ( t, &t, "\\en", sizeof (terminator) );
+ do s++; while (*s != '{');
+ *ln = strchr (s, '}') ;
+ if (*ln == NULL) error ("Can't find '}' after \\TransformNotes.");
+ (*ln)++;
+ }
+
+ else if ( prefix("\\notes", *ln) ||
+ prefix("\\Notes", *ln) ||
+ prefix("\\NOtes", *ln) ||
+ prefix("\\NOTes", *ln) ||
+ prefix("\\NOTEs", *ln) ||
+ prefix("\\nnotes", *ln) ||
+ prefix("\\vnotes", *ln) ||
+ prefix("\\znotes", *ln)
+ )
+ {
+ if (debug > 1) printf ("%s\n", " Processing notes");
+ analyze_notes (ln);
+ t = strpbrk (*ln, "\\\n");
+ if (t == NULL)
+ { *ln = *ln + strlen (*ln); return; }
+ *ln = t;
+ }
+
+ else if ( prefix("\\def\\atnextbar", *ln))
+ {
+ if (debug > 1) printf ("%s\n", " Processing \\def\\atnextbar");
+ s = strstr (*ln, "\\znotes");
+ if (s != NULL)
+ {
+ *ln = s;
+ analyze_notes (ln);
+ }
+ t = strpbrk (*ln, "\\");
+ if (t == NULL)
+ { *ln = *ln + strlen (*ln); return; }
+ *ln = t;
+ }
+
+ else if ( prefix("\\def", *ln) )
+ *ln = *ln + strlen (*ln);
+
+ else /* anything else */
+ {
+ if (debug > 1) printf (" Processing ");
+ t = strpbrk (*ln+1, "\\\n");
+ if (t == NULL) t = *ln + strlen (*ln);
+ if (debug > 1)
+ { char *s = *ln; do {putchar (*s); s++;} while (s != t); puts ("");}
+ *ln = t;
+ }
+}
+
+PRIVATE void
+process_line (void)
+{
+ char *ln;
+ ln = &line[0];
+ while ( *ln != '\0')
+ {
+ while (*ln == ' ') { ln++;}
+ if (*ln == '%' || *ln == '\n') return;
+ process_command (&ln);
+ } /* *ln == '\0' */
+}
+
+PRIVATE void
+process_score (void)
+/* process .tex file */
+{
+ int c; int i;
+ lineno = 0;
+ ninstr = 1;
+ nerrors = 0;
+ staffs[0] = 0;
+ for (i = 1; i<12; i++) staffs[i] = 1;
+ terminator[0] = '\0'; /* either \en or \enotes */
+ while ( (c = getc (infile)) != EOF )
+ {
+ ungetc (c, infile);
+ if (fgets(line, LINE_LEN, infile) == NULL) error("IO error");
+ if (strlen (line) == LINE_LEN-1) error("Line too long.");
+ lineno++;
+ if (debug > 0) printf ("Processing line %d.\n", lineno);
+ process_line ();
+ if (nerrors > NERRORSMAX) {
+ puts ("\nToo many errors; processing of this file aborted.");
+ return;
+ }
+ } /* c == EOF */
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ int c;
+ char today[12];
+ time_t mytime;
+# define NOPTS 4
+ struct option longopts[NOPTS] =
+ { { "help", 0, NULL, 'h'},
+ { "version", 0, NULL, 'v'},
+ { "debug", 0, NULL, 'd'},
+ { NULL, 0, NULL, 0}
+ };
+
+ time (&mytime);
+ strftime (today, 11, "%Y-%m-%d", localtime (&mytime) );
+ printf ("This is msxlint, version %s.\n", version);
+ c = getopt_long (argc, argv, "hvd", longopts, NULL);
+ while (c != -1)
+ {
+ switch (c)
+ {
+ case 'h':
+ usage ();
+ puts ( "Please report bugs to rdt@cs.queensu.ca." );
+ exit (0);
+ case 'v':
+ exit (0);
+ case 'd':
+ debug++;
+ break;
+ case '?':
+ exit (EXIT_FAILURE);
+ default:
+ fprintf (stderr,"Function getopt returned character code 0%o.\n",
+ (unsigned int) c);
+ exit (EXIT_FAILURE);
+ }
+ c = getopt_long (argc, argv, "hvd", longopts, NULL);
+ }
+ puts ( "Copyright (C) 2014-15 R. D. Tennent" );
+ puts ( "School of Computing, Queen's University, rdt@cs.queensu.ca" );
+ puts ( "License GNU GPL version 2 or later <http://gnu.org/licences/gpl.html>." );
+ puts ( "There is NO WARRANTY, to the extent permitted by law." );
+
+ if (optind == argc)
+ {
+ infile = stdin;
+ printf ("\nProcessing stdin.\n\n");
+ process_score ();
+ }
+ else
+ do
+ {
+ infilename[0] = '\0';
+ infilename_n = infilename;
+ append (infilename, &infilename_n, argv[optind], sizeof (infilename));
+ if (!suffix (".tex", infilename))
+ append (infilename, &infilename_n, ".tex", sizeof (infilename));
+ infile = fopen (infilename, "r");
+ if (infile == NULL)
+ {
+ fprintf (stderr,"Can't open %s\n", infilename);
+ optind++;
+ continue;
+ }
+ printf ("\nProcessing %s.\n\n", infilename);
+ process_score ();
+ optind++;
+ }
+ while (optind < argc);
+
+ return 0;
+}