
| Current Path : /proc/thread-self/root/usr/local/lib/python3.8/dist-packages/iftlib/abc/56/abcm2ps-8.5.2/ |
Linux ift1.ift-informatik.de 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64 |
| Current File : //proc/thread-self/root/usr/local/lib/python3.8/dist-packages/iftlib/abc/56/abcm2ps-8.5.2/front.c |
/*
* ABC front-end parser
*
* This file is part of abcm2ps.
*
* Copyright (C) 2011-2015 Jean-François Moine (http://moinejf.free.fr)
*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifdef WIN32
#define strncasecmp _strnicmp
#define strdup _strdup
#endif
#include "abc2ps.h"
#include "slre.h"
static unsigned char *dst;
static int offset, size;
static unsigned char *selection;
static int latin, skip;
static char prefix[4] = {'%'};
/*
* translation table from the ABC draft version 2
* ` grave
* ' acute
* ^ circumflex
* , cedilla
* " umlaut
* ~ tilde
* o ring
* = macron or stroke
* / slash
* ; ogonek
* v caron
* u breve
* : long Hungarian umlaut
* . dot / dotless
* else, ligatures
* ae ss ng
*/
/* !! each table item is 3 bytes: 1 char, 1 UTF-8 char on 2 bytes */
static unsigned char grave[] = "AÀEÈIÌOÒUÙaàeèiìoòuù";
static unsigned char acute[] = "AÁEÉIÍOÓUÚYÝaáeéiíoóuúyýSŚZŹsśzźRŔLĹCĆNŃrŕlĺcćnń";
static unsigned char circumflex[] = "AÂEÊIÎOÔUÛaâeêiîoôuûHĤJĴhĥjĵCĈGĜSŜcĉgĝsŝ";
static unsigned char cedilla[] = "CÇcçSŞsşTŢtţRŖLĻGĢrŗlļgģNŅKĶnņkķ";
static unsigned char umlaut[] = "AÄEËIÏOÖUÜYŸaäeëiïoöuüyÿ";
static unsigned char tilde[] = "AÃNÑOÕaãnñoõIĨiĩUŨuũ";
static unsigned char ring[] = "AÅaåUŮuů";
static unsigned char macron[] = "AĀDĐEĒHĦIĪOŌTŦUŪaādđeēhħiīoōtŧuū"; /* and stroke! */
static unsigned char slash[] = "OØoøDĐdđLŁlł";
static unsigned char ogonek[] = "AĄEĘIĮUŲaąeęiįuų";
static unsigned char caron[] = "LĽSŠTŤZŽlľsštťzžCČEĚDĎNŇRŘcčeědďnňrř";
static unsigned char breve[] = "AĂaăEĔeĕGĞgğIĬiĭOŎoŏUŬuŭ";
static unsigned char hungumlaut[] = "OŐUŰoőuű";
static unsigned char dot[] = "ZŻzżIİiıCĊcċGĠgġEĖeė";
/* the items of this table are 4 bytes long */
static unsigned char ligature[] = "AAÅaaåAEÆaeæccçcCÇDHÐdhðngŋOEŒoeœssßTHÞthþ";
/* latin conversion tables - range 0xa0 .. 0xff */
static unsigned char latin2[] = {
" Ą˘Ł¤ĽŚ§¨ŠŞŤŹŽŻ°ą˛ł´ľśˇ¸šşťź˝žż"
"ŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖ×ŘŮÚŰÜÝŢß"
"ŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙"
};
static unsigned char latin3[] = {
" Ħ˘£¤ Ĥ§¨İŞĞĴ ݰħ²³´µĥ·¸ışğĵ½ ż"
"ÀÁÂ ÄĊĈÇÈÉÊËÌÍÎÏ ÑÒÓÔĠÖ×ĜÙÚÛÜŬŜß"
"àáâ äċĉçèéêëìíîï ñòóôġö÷ĝùúûüŭŝ˙"
};
static unsigned char latin4[] = {
" ĄĸŖ¤Ĩϧ¨ŠĒĢŦޝ°ą˛ŗ´ĩšēģŧŊžŋ"
"ĀÁÂÃÄÅÆĮČÉĘËĖÍÎĪĐŅŌĶÔÕÖרŲÚÛÜŨŪß"
"āáâãäåæįčéęëėíîīđņōķôõö÷øųúûüũū˙"
};
static unsigned char latin5[] = {
" ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿"
"ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏĞÑÒÓÔÕÖרÙÚÛÜİŞß"
"àáâãäåæçèéêëìíîïğñòóôõö÷øùúûüışÿ"
};
static unsigned char latin6[] = {
" ĄĒĢĪĨͧĻĐŠŦŽŪŊ°ąēģīĩķ·ļđšŧž―ūŋ"
"ĀÁÂÃÄÅÆĮČÉĘËĖÍÎÏÐŅŌÓÔÕÖŨØŲÚÛÜÝÞß"
"āáâãäåæįčéęëėíîïðņōóôõöũøųúûüýþĸ"
};
static unsigned char *latin_tb[5] = {
latin2, latin3, latin4, latin5, latin6
};
/* add text to the output buffer */
static void txt_add(unsigned char *s, int sz)
{
if (skip)
return;
if (offset + sz > size) {
size = (offset + sz + 8191) / 8192 * 8192;
if (!dst)
dst = malloc(size);
else
dst = realloc(dst, size);
if (!dst) {
fprintf(stderr, "Out of memory - abort\n");
exit(EXIT_FAILURE);
}
}
memcpy(dst + offset, s, sz);
offset += sz;
}
/* add text to the output buffer translating
* the escape sequences and the non utf-8 characters */
static void txt_add_cnv(unsigned char *s, int sz)
{
unsigned char *p, c, tmp[4];
int in_string = 0;
p = s;
while (sz > 0) {
switch (*p) {
case '"':
in_string = !in_string;
break;
case '%':
if (in_string)
break;
while (--p >= s) { // start of comment
if (*p != ' ' && *p != '\t')
break;
}
p++;
goto done;
case '\\':
if (sz >= 4 /* \ooo */
&& p[1] >= '0' && p[1] <= '3'
&& p[2] >= '0' && p[2] <= '7'
&& p[3] >= '0' && p[3] <= '7') {
c = ((p[1] - '0') << 6)
+ ((p[2] - '0') << 3)
+ p[3] - '0';
if (p != s)
txt_add(s, (int) (p - s));
p += 4;
s = p;
sz -= 4;
switch (c) { /* convert the accidentals */
case 0x01:
case 0x81:
tmp[0] = 0xe2;
tmp[1] = 0x99;
tmp[2] = 0xaf;
txt_add(tmp, 3);
continue;
case 0x02:
case 0x82:
tmp[0] = 0xe2;
tmp[1] = 0x99;
tmp[2] = 0xad;
txt_add(tmp, 3);
continue;
case 0x03:
case 0x83:
tmp[0] = 0xe2;
tmp[1] = 0x99;
tmp[2] = 0xae;
txt_add(tmp, 3);
continue;
case 0x04:
case 0x84:
tmp[0] = 0xf0;
tmp[1] = 0x9d;
tmp[2] = 0x84;
tmp[3] = 0xaa;
txt_add(tmp, 4);
continue;
case 0x05:
case 0x85:
tmp[0] = 0xf0;
tmp[1] = 0x9d;
tmp[2] = 0x84;
tmp[3] = 0xab;
txt_add(tmp, 4);
continue;
}
if (c >= 0x80 && latin > 0)
goto latin;
tmp[0] = c;
txt_add(tmp, 1);
continue;
}
if (sz >= 6 /* \uxxxx */
&& p[1] == 'u'
&& isxdigit(p[2])
&& isxdigit(p[3])
&& isxdigit(p[4])
&& isxdigit(p[5])) {
int i, v;
v = 0;
for (i = 2; i < 6; i++) {
v <<= 4;
c = p[i];
if (c <= '9')
v += c - '0';
else if (c <= 'F')
v += c - 'A' + 10;
else
v += c - 'a' + 10;
}
if (p != s)
txt_add(s, (int) (p - s));
p += 6;
sz -= 6;
if ((v & 0xdc00) == 0xd800 /* surrogates */
&& sz >= 6
&& *p == '\\'
&& p[1] == 'u'
&& isxdigit(p[2])
&& isxdigit(p[3])
&& isxdigit(p[4])
&& isxdigit(p[5])) {
int v2;
v = (v - 0xd7c0) << 10;
v2 = 0;
for (i = 2; i < 6; i++) {
v2 <<= 4;
c = p[i];
if (c <= '9')
v2 += c - '0';
else if (c <= 'F')
v2 += c - 'A' + 10;
else
v2 += c - 'a' + 10;
}
v2 -= 0xdc00;
v += v2;
p += 6;
sz -= 6;
}
//fixme: else error
s = p;
if (v < 0x80) { /* convert to UTF-8 */
tmp[0] = v;
i = 1;
} else if (v < 0x800) {
tmp[0] = 0xc0 | (v >> 6);
tmp[1] = 0x80 | (v & 0x3f);
i = 2;
} else if (v < 0x10000) {
tmp[0] = 0xe0 | (v >> 12);
tmp[1] = 0x80 | ((v >> 6) & 0x3f);
tmp[2] = 0x80 | (v & 0x3f);
i = 3;
} else {
tmp[0] = 0xf0 | (v >> 18);
tmp[1] = 0x80 | ((v >> 12) & 0x3f);
tmp[2] = 0x80 | ((v >> 6) & 0x3f);
tmp[3] = 0x80 | (v & 0x3f);
i = 4;
}
txt_add(tmp, i);
continue;
}
if (sz >= 3) {
unsigned char *q;
switch (p[1]) {
case '`': q = grave; break;
case '\'': q = acute; break;
case '^': q = circumflex; break;
case ',': q = cedilla; break;
case '"': q = umlaut; break;
case '~': q = tilde; break;
case 'o': q = ring; break;
case '=': q = macron; break;
case '/': q = slash; break;
case ';': q = ogonek; break;
case 'v': q = caron; break;
case 'u': q = breve; break;
case 'H':
case ':': q = hungumlaut; break;
case '.': q = dot; break;
default:
q = ligature;
do {
if (*q == p[1]
&& q[1] == p[2])
break;
q += 4;
} while (*q != '\0');
if (*q != '\0') {
if (p != s)
txt_add(s, (int) (p - s));
txt_add(q + 2, 2);
p += 3;
sz -= 3;
s = p;
continue;
}
q = 0;
break;
}
if (q != 0) {
do {
if (*q == p[2])
break;
q += 3;
} while (*q != '\0');
if (*q != '\0') {
if (p != s)
txt_add(s, (int) (p - s));
txt_add(q + 1, 2);
p += 3;
sz -= 3;
s = p;
continue;
}
}
}
p++;
sz--;
if (sz > 0) {
p++;
sz--;
}
continue;
}
if (*p >= 0x80 && latin > 0) {
if (p != s)
txt_add(s, (int) (p - s));
c = *p++;
s = p;
sz--;
latin:
if (c < 0xa0 || latin == 1) {
tmp[0] = 0xc0 | ((c >> 6) & 0x03);
tmp[1] = 0x80 | (c & 0x3f);
txt_add(tmp, 2);
} else {
unsigned char *q;
q = latin_tb[latin - 2];
txt_add(q + (c - 0xa0) * 2, 2);
}
continue;
}
p++;
sz--;
}
done:
if (p != s)
txt_add(s, (int) (p - s));
}
static void txt_add_eos(char *fname, int linenum)
{
static unsigned char eos = '\0';
/* special case for continuation lines in ABC version 2.0 */
if (parse.abc_vers == (2 << 16)
&& offset > 0
&& dst[offset - 1] == '\\') {
offset--;
return;
}
txt_add(&eos, 1);
abc_parse((char *) dst, fname, linenum);
offset = 0;
}
/* get the ABC version */
static void get_vers(char *p)
{
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);
parse.abc_vers = (i << 16) + (j << 8) + k;
}
/* check if the current tune is to be selected */
static int tune_select(unsigned char *s)
{
struct slre slre;
unsigned char *p, *sel;
/* if there is a list of tune indexes,
* check the tune index */
sel = selection;
if (isdigit(*sel)) {
int tune_number, cur_sel, end_sel, n;
/* get the tune number ('s' points to X:) */
tune_number = strtod((char *) s + 2, 0);
/* search it in the number list */
for (;;) {
if (sscanf((char *) sel, "%d%n", &cur_sel, &n) != 1)
break;
sel += n;
if (*sel == '-') {
sel++;
if (sscanf((char *) sel, "%d%n", &end_sel, &n) != 1)
end_sel = ~0u >> 1;
else
sel += n;
} else {
end_sel = cur_sel;
}
if (tune_number >= cur_sel && tune_number <= end_sel)
return 1;
if (*sel != ',')
break;
sel++;
}
if (*sel == '\0')
return 0;
}
for (p = s + 2; ; p++) {
switch (*p) {
case '\0':
return 0;
default:
continue;
case '\n':
case '\r':
break;
}
if (p[1] != 'K' || p[2] != ':')
continue;
p += 3;
while (*p != '\n' && *p != '\r' && *p != '\0')
p++;
if (*p != '\0')
p++; /* keep the EOL for RE with '\s' */
break;
}
//fixme: should compile only one time
if (!slre_compile(&slre, (char *) sel))
return 0;
return slre_match(&slre, (char *) s, p - s, 0);
}
/* -- front end parser -- */
void frontend(unsigned char *s,
int ftype,
char *fname,
int linenum)
{
unsigned char *p, *q, c, *begin_end, sep;
int i, l, state, str_cnv_p, histo, end_len;
char prefix_sav[4];
int latin_sav = 0; /* have C compiler happy */
begin_end = NULL;
end_len = 0;
histo = 0;
state = 0;
if (ftype == FE_ABC
&& strncmp((char *) s, "%abc-", 5) == 0) {
get_vers((char *) s + 5);
while (*s != '\0'
&& *s != '\r'
&& *s != '\n')
s++;
if (*s != '\0') {
s++;
if (s[-1] == '\r' && *s == '\n')
s++;
}
linenum++;
}
/* if unknown encoding, check if latin1 or utf-8 */
if (ftype == FE_ABC
&& parse.abc_vers >= ((2 << 16) | (1 << 8))) { // if ABC version >= 2.1
latin = 0; // always UTF-8
} else {
for (p = s; *p != '\0'; p++) {
c = *p;
if (c == '\\') {
if (!isdigit(p[1]))
continue;
if ((p[1] == '0' || p[1] == '2')
&& p[2] == '0') /* accidental */
continue;
latin = 1;
break;
}
if (c < 0x80)
continue;
if (c >= 0xc2) {
if ((p[1] & 0xc0) == 0x80) {
latin = 0;
break;
}
}
latin = 1;
break;
}
}
latin_sav = latin; /* (have gcc happy) */
/* scan the file */
skip = 0;
while (*s != '\0') {
/* get a line */
str_cnv_p = 0;
p = s;
while (*p != '\0'
&& *p != '\r'
&& *p != '\n') {
if (*p == '\\'
|| *p == '%'
|| (latin > 0 && *p >= 0x80))
str_cnv_p = 1;
p++;
}
l = p - s;
if (*p != '\0') {
p++;
if (p[-1] == '\r' && *p == '\n') /* (DOS) */
p++;
}
linenum++;
if (skip) {
if (l != 0)
goto ignore;
skip = 0;
}
if (begin_end) {
if (ftype == FE_FMT) {
if (strncmp((char *) s, "end", 3) == 0
&& strncmp((char *) s + 3,
(char *) begin_end, end_len) == 0) {
begin_end = NULL;
goto next_eol;
}
if (*s == '%')
goto ignore; /* comment */
goto next;
}
if (*s == '%' && strchr(prefix, s[1])) {
q = s + 2;
while (*q == ' ' || *q == '\t')
q++;
if (strncmp((char *) q, "end", 3) == 0
&& strncmp((char *) q + 3,
(char *) begin_end, end_len) == 0) {
begin_end = NULL;
goto next_eol;
}
}
if (strncmp("ps", (char *) begin_end, end_len) == 0) {
if (*s == '%')
goto ignore; /* comment */
} else {
if (*s == '%' && strchr(prefix, s[1])) {
s += 2;
l -= 2;
}
}
goto next;
}
while (l > 0 && isspace(s[l - 1]))
l--;
if (l == 0) { /* empty line */
switch (state) {
default:
goto ignore;
case 1:
fprintf(stderr,
"Line %d: Empty line in tune header - K:C added\n",
linenum);
txt_add((unsigned char *) "K:C", 3);
txt_add_eos(fname, linenum);
/* fall thru */
case 2:
state = 0;
strcpy(prefix, prefix_sav);
latin = latin_sav;
break;
}
goto next_eol;
}
if (histo) { /* H: continuation */
if ((s[1] == ':'
&& (isalpha(*s) || *s == '+'))
|| (*s == '%' && strchr(prefix, s[1]))) {
histo = 0;
} else {
txt_add((unsigned char *) "H:", 2);
goto next;
}
}
/* special case 'space* "%" ' */
if (*s == ' ' || *s == '\t') {
q = s;
do {
q++;
} while (*q == ' ' || *q == '\t');
if (*q == '%')
goto ignore;
}
if (ftype == FE_PS) {
if (*s == '%')
goto ignore;
goto next;
}
/* treat the pseudo-comments */
if (ftype == FE_FMT) {
if (*s == '%')
goto ignore;
goto pscom;
}
if (*s == 'I' && s[1] == ':') {
s += 2;
l -= 2;
while (*s == ' ' || *s == '\t') {
s++;
l--;
}
txt_add((unsigned char *) "%%", 2);
goto info;
}
if (*s == '%') {
if (!strchr(prefix, s[1])) /* pure comment */
goto ignore;
s += 2;
l -= 2;
if (strncmp((char *) s, "abcm2ps ", 8) == 0) {
s += 8;
l -= 8;
while (*s == ' ' || *s == '\t') {
s++;
l--;
}
for (i = 0; i < sizeof prefix - 1; i++) {
if (*s == ' ' || *s == '\t'
|| --l < 0)
break;
prefix[i] = *s++;
}
if (i == 0)
prefix[i++] = '%';
prefix[i] = '\0';
goto ignore;
}
if (strncmp((char *) s, "abc-version ", 12) == 0) {
get_vers((char *) s + 12);
goto ignore;
}
pscom:
while (*s == ' ' || *s == '\t') {
s++;
l--;
}
txt_add((unsigned char *) "%%", 2);
if (strncmp((char *) s, "begin", 5) == 0) {
q = begin_end = s + 5;
while (!isspace(*q))
q++;
end_len = q - begin_end;
goto next;
}
info:
if (strncmp((char *) s, "encoding ", 9) == 0
|| strncmp((char *) s, "abc-charset ", 12) == 0) {
if (*s == 'e')
q = s + 9;
else
q = s + 12;
while (*q == ' ' || *q == '\t')
q++;
if (strncasecmp((char *) q, "latin", 5) == 0) {
q += 5;
} else if (strncasecmp((char *) q, "iso-8859-", 9) == 0) {
q += 9;
} else if (strncasecmp((char *) q, "utf-8", 5) == 0
|| strncasecmp((char *) q, "native", 6) == 0) {
latin = 0;
goto next;
} else if (!isdigit(*q)) {
goto next; /* unknown charset */
}
switch (*q) {
case '1':
if (q[1] == '0')
latin = 6;
else
latin = 1;
break;
case '2': latin = 2; break;
case '3': latin = 3; break;
case '4': latin = 4; break;
case '5':
if (q[-1] != '-')
latin = 5;
break;
case '6':
if (q[-1] != '-')
latin = 6;
break;
/*fixme: iso-8859 5..8 not treated */
case '9': latin = 5; break;
}
goto next;
}
if (strncmp((char *) s, "format ", 7) == 0
|| strncmp((char *) s, "abc-include ", 12) == 0) {
int skip_sav;
if (*s == 'f')
s += 7;
else
s += 12;
while (*s == ' ' || *s == '\t')
s++;
q = s;
while (*q != '\0'
&& *q != '%'
&& *q != '\n'
&& *q != '\r')
q++;
while (q[-1] == ' ')
q--;
sep = *q;
*q = '\0';
skip_sav = skip;
offset = 0;
include_file(s);
skip = skip_sav;
*q = sep;
goto ignore;
}
if (strncmp((char *) s, "select", 6) == 0) {
s += 6;
if (*s == '\n') { /* select clear */
q = s;
} else if (*s != ' ' && *s != '\t') {
goto next;
} else {
while (*s == ' ' || *s == '\t')
s++;
q = s;
while (*q != '\0'
&& *q != '%'
&& *q != '\n'
&& *q != '\r')
q++;
while (q[-1] == ' ' || q[-1] == '\t')
q--;
if (strncmp((char *) q - 5, " lock", 5) == 0)
q -= 5;
}
if (selection) {
free(selection);
selection = NULL;
}
if (q != s) {
sep = *q;
*q = '\0';
selection = (unsigned char *) strdup((char *) s);
*q = sep;
}
offset = 0;
goto ignore;
}
goto next;
}
/* treat the information fields */
if (s[1] == ':' && (isalpha(*s) || *s == '+')) {
c = *s;
switch (c) {
case 'I': /* treat as a pseudo-comment */
s += 2;
l -= 2;
goto pscom;
case 'X':
switch (state) {
case 1:
fprintf(stderr,
"Line %d: X: found in tune header - K:C added\n",
linenum);
txt_add((unsigned char *) "K:C", 3);
txt_add_eos(fname, linenum);
txt_add_eos(fname, linenum); /* empty line */
break;
case 2:
txt_add_eos(fname, linenum); /* no empty line - minor error */
break;
}
if (selection) {
skip = !tune_select(s);
if (skip)
goto ignore;
}
state = 1;
strcpy(prefix_sav, prefix);
latin_sav = latin;
break;
case 'U':
break;
case 'H':
histo = 1;
break;
default:
if (state == 0 /* if global */
&& strchr("dKPQsVWw", *s) != NULL)
goto ignore;
if (*s == 'K')
state = 2;
break;
}
txt_add(s, 2);
s += 2;
l -= 2;
while (*s == ' ' || *s == '\t') {
s++;
l--;
}
str_cnv_p = 1;
goto next;
}
/* treat the music lines */
if (state == 0) /* if not in tune */
goto ignore;
#if 0
// what was this used for?
if (!str_cnv_p)
goto next;
str_cnv_p = 0;
for (i = 0; i < l; i++) {
if (s[i] != '"')
continue;
i++;
txt_add(s, i);
s += i;
l -= i;
for (i = 0; i < l; i++) {
if (s[i] == '"' && s[i - 1] != '\\')
break;
}
//fixme: if i == l, no end of string - error
txt_add_cnv(s, i);
s += i;
l -= i;
i = 0;
}
#endif
next:
if (str_cnv_p)
txt_add_cnv(s, l);
else
txt_add(s, l);
if (begin_end)
txt_add((unsigned char *) "\n", 1);
else
next_eol:
txt_add_eos(fname, linenum);
ignore:
s = p;
}
if (state == 1)
fprintf(stderr,
"Line %d: Unexpected EOF in header definition\n",
linenum);
if (begin_end)
fprintf(stderr,
"Line %d: No %%%%end after %%%%begin\n",
linenum);
abc_eof();
}