/*
* Gregorio is a program that translates gabc files to GregorioTeX.
* This file provides functions to dump out Gregorio structures.
*
* Copyright (C) 2007-2021 The Gregorio Project (see CONTRIBUTORS.md)
*
* This file is part of Gregorio.
*
* 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 3 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 "config.h"
#include
#include
#include "bool.h"
#include "struct.h"
#include "unicode.h"
#include "messages.h"
#include "plugins.h"
#include "support.h"
static const char *dump_style_to_string(grestyle_style style)
{
static char buf[50];
gregorio_snprintf(buf, sizeof buf, "%16s", grestyle_style_to_string(style));
return buf;
}
void dump_write_characters(FILE *const f,
const gregorio_character * current_character)
{
while (current_character) {
fprintf(f,
"---------------------------------------------------------------------\n");
if (current_character->is_character) {
fprintf(f, " character ");
gregorio_print_unichar(f, current_character->cos.character);
fprintf(f, "\n");
} else {
switch (current_character->cos.s.type) {
case ST_T_BEGIN:
fprintf(f, " beginning of style %s\n",
dump_style_to_string(current_character->cos.s.style));
break;
case ST_T_END:
fprintf(f, " end of style %s\n",
dump_style_to_string(current_character->cos.s.style));
break;
default:
/* not reachable unless there's a programming error */
/* LCOV_EXCL_START */
fprintf(f, " !! IMPROPER STYLE !! %s\n",
dump_style_to_string(current_character->cos.s.style));
break;
/* LCOV_EXCL_STOP */
}
}
current_character = current_character->next_character;
}
}
static const char *dump_bool(bool value) {
return value? "true" : "false";
}
static const char *dump_pitch(const char height, const char highest_pitch) {
static char buf[20];
if (height >= LOWEST_PITCH && height <= highest_pitch) {
char pitch = height + 'a' - LOWEST_PITCH;
if (pitch == 'o') {
pitch = 'p';
}
gregorio_snprintf(buf, 20, "%c", pitch);
} else {
/* not reachable unless there's a programming error */
gregorio_snprintf(buf, 20, "?%d", height); /* LCOV_EXCL_LINE */
}
return buf;
}
static void dump_hepisema_adjustment(FILE *const f, const gregorio_note *note,
const gregorio_sign_orientation orientation, const char *const which) {
unsigned short index = note->he_adjustment_index[orientation];
if (index) {
gregorio_hepisema_adjustment *adj = gregorio_get_hepisema_adjustment(
index);
fprintf(f, " %s hepisema group %d\n", which, index);
fprintf(f, " %s hep. vbasepos %d (%s)\n", which,
adj->vbasepos,
gregorio_hepisema_vbasepos_to_string(adj->vbasepos));
if (adj->nudge) {
fprintf(f, " %s hepisema nudge %s\n", which, adj->nudge);
}
}
}
void dump_write_score(FILE *f, gregorio_score *score)
{
gregorio_voice_info *voice_info = score->first_voice_info;
int i;
int annotation_num;
gregorio_syllable *syllable;
gregorio_header *header;
gregorio_assert(f, dump_write_score, "call with NULL file", return);
fprintf(f,
"=====================================================================\n"
" SCORE INFOS\n"
"=====================================================================\n");
if (score->number_of_voices) {
fprintf(f, " number_of_voices %d\n",
score->number_of_voices);
}
if (score->name) {
fprintf(f, " name %s\n", score->name);
}
if (score->gabc_copyright) {
fprintf(f, " gabc_copyright %s\n", score->gabc_copyright);
}
if (score->score_copyright) {
fprintf(f, " score_copyright %s\n", score->score_copyright);
}
if (score->author) {
fprintf(f, " author %s\n", score->author);
}
if (score->mode) {
fprintf(f, " mode %s\n", score->mode);
}
if (score->mode_modifier) {
fprintf(f, " mode_modifier %s\n", score->mode_modifier);
}
if (score->mode_differentia) {
fprintf(f, " mode_differentia %s\n", score->mode_differentia);
}
if (score->staff_lines != 4) {
fprintf(f, " staff_lines %d\n", (int)score->staff_lines);
}
if (score->nabc_lines) {
fprintf(f, " nabc_lines %d\n", (int)score->nabc_lines);
}
if (score->legacy_oriscus_orientation) {
fprintf(f, " oriscus-orientation legacy\n");
}
fprintf(f, "\n\n"
"=====================================================================\n"
" HEADERS\n"
"=====================================================================\n");
for (header = score->headers; header; header = header->next) {
fprintf(f, " %-25s %s\n", header->name, header->value);
}
fprintf(f, "\n\n"
"=====================================================================\n"
" VOICES INFOS\n"
"=====================================================================\n");
for (i = 0; i < score->number_of_voices; i++) {
fprintf(f, " Voice %d\n", i + 1);
if (voice_info->initial_clef.line) {
fprintf(f, " initial_key %d (%c%d)\n",
gregorio_calculate_new_key(voice_info->initial_clef),
gregorio_clef_to_char(voice_info->initial_clef.clef),
voice_info->initial_clef.line);
if (voice_info->initial_clef.flatted) {
fprintf(f, " flatted_key true\n");
}
if (voice_info->initial_clef.secondary_line) {
fprintf(f, " secondary_clef %c%d\n",
gregorio_clef_to_char(
voice_info->initial_clef.secondary_clef),
voice_info->initial_clef.secondary_line);
if (voice_info->initial_clef.secondary_flatted) {
fprintf(f, " secondary_flatted_key true\n");
}
}
}
for (annotation_num = 0; annotation_num < MAX_ANNOTATIONS;
++annotation_num) {
if (score->annotation[annotation_num]) {
fprintf(f, " annotation %s\n",
score->annotation[annotation_num]);
}
}
voice_info = voice_info->next_voice_info;
}
fprintf(f, "\n\n"
"=====================================================================\n"
" SCORE\n"
"=====================================================================\n");
for (syllable = score->first_syllable; syllable;
syllable = syllable->next_syllable) {
gregorio_element *element;
fprintf(f, " type 0 (GRE_SYLLABLE)\n");
if (syllable->position) {
fprintf(f, " position %d (%s)\n",
syllable->position,
gregorio_word_position_to_string(syllable->position));
}
if (syllable->no_linebreak_area != NLBA_NORMAL) {
fprintf(f, " no line break area %s\n",
gregorio_nlba_to_string(syllable->no_linebreak_area));
}
if (syllable->euouae != EUOUAE_NORMAL) {
fprintf(f, " euouae %s\n",
gregorio_euouae_to_string(syllable->euouae));
}
if (syllable->clear) {
fprintf(f, " clear true\n");
}
if (syllable->text) {
if (syllable->translation) {
fprintf(f, "\n Text\n");
}
dump_write_characters(f, syllable->text);
}
if ((syllable->translation
&& syllable->translation_type != TR_WITH_CENTER_END)
|| syllable->translation_type == TR_WITH_CENTER_END) {
fprintf(f, "\n Translation type %s",
gregorio_tr_centering_to_string
(syllable->translation_type));
if (syllable->translation_type == TR_WITH_CENTER_END) {
fprintf(f, "\n");
}
}
if (syllable->translation) {
fprintf(f, "\n Translation\n");
dump_write_characters(f, syllable->translation);
}
if (syllable->abovelinestext) {
fprintf(f, "\n Abovelinestext\n %s", syllable->abovelinestext);
}
for (element = *syllable->elements; element; element = element->next) {
gregorio_glyph *glyph;
fprintf(f, "---------------------------------------------------------------------\n");
if (element->type) {
fprintf(f, " type %d (%s)\n",
element->type, gregorio_type_to_string(element->type));
}
switch (element->type) {
case GRE_CUSTOS:
if (element->u.misc.pitched.pitch) {
fprintf(f, " pitch %s\n",
dump_pitch(element->u.misc.pitched.pitch,
score->highest_pitch));
}
if (element->u.misc.pitched.force_pitch) {
fprintf(f, " force_pitch true\n");
}
break;
case GRE_SUPPRESS_CUSTOS:
/* not handling this would generate an error below */
break;
case GRE_SPACE:
if (element->u.misc.unpitched.info.space) {
char *factor = element->u.misc.unpitched.info.
ad_hoc_space_factor;
fprintf(f, " space %d (%s)%s%s\n",
element->u.misc.unpitched.info.space,
gregorio_space_to_string(
element->u.misc.unpitched.info.space),
factor? " x " : "", factor? factor : "");
}
break;
case GRE_TEXVERB_ELEMENT:
fprintf(f, " TeX string \"%s\"\n",
gregorio_texverb(element->texverb));
break;
case GRE_NLBA:
fprintf(f, " nlba %d (%s)\n",
element->u.misc.unpitched.info.nlba,
gregorio_nlba_to_string(element->u.misc.unpitched.info.
nlba));
break;
case GRE_ALT:
fprintf(f, " Above lines text \"%s\"\n",
gregorio_texverb(element->texverb));
break;
case GRE_BAR:
if (element->u.misc.unpitched.info.bar) {
fprintf(f, " bar %d (%s)\n",
element->u.misc.unpitched.info.bar,
gregorio_bar_to_string(element->u.misc.unpitched.
info.bar));
if (element->u.misc.unpitched.special_sign) {
fprintf(f, " special sign %d (%s)\n",
element->u.misc.unpitched.special_sign,
gregorio_sign_to_string(element->
u.misc.unpitched.special_sign));
}
}
break;
case GRE_CLEF:
if (element->u.misc.clef.line) {
fprintf(f, " clef %d (%c%d)\n",
gregorio_calculate_new_key(element->u.misc.clef),
gregorio_clef_to_char(element->u.misc.clef.clef),
element->u.misc.clef.line);
if (element->u.misc.clef.flatted) {
fprintf(f, " flatted_key true\n");
}
if (element->u.misc.clef.secondary_line) {
fprintf(f, " secondary_clef %c%d\n",
gregorio_clef_to_char(
element->u.misc.clef.secondary_clef),
element->u.misc.clef.secondary_line);
if (element->u.misc.clef.secondary_flatted) {
fprintf(f, " secondary_flatted_key true\n");
}
}
}
break;
case GRE_END_OF_LINE:
if (element->u.misc.unpitched.info.eol_ragged) {
fprintf(f, " ragged true\n");
}
if (element->u.misc.unpitched.info.eol_forces_custos) {
fprintf(f, " forces custos %s\n",
dump_bool(element
->u.misc.unpitched.info.eol_forces_custos_on));
}
break;
case GRE_ELEMENT:
for (glyph = element->u.first_glyph; glyph;
glyph = glyph->next) {
gregorio_note *note;
fprintf(f, "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n");
if (glyph->type) {
fprintf(f, " type %d (%s)\n",
glyph->type, gregorio_type_to_string(glyph->
type));
}
switch (glyph->type) {
case GRE_TEXVERB_GLYPH:
fprintf(f, " TeX string \"%s\"\n",
gregorio_texverb(glyph->texverb));
break;
case GRE_SPACE:
fprintf(f, " space %d (%s)\n",
glyph->u.misc.unpitched.info.space,
gregorio_space_to_string(glyph->u.misc.
unpitched.info.space));
break;
case GRE_GLYPH:
fprintf(f, " glyph_type %d (%s)\n",
glyph->u.notes.glyph_type,
gregorio_glyph_type_to_string(glyph->u.notes.
glyph_type));
if (glyph->u.notes.is_cavum) {
fprintf(f, " is_cavum true\n");
}
if (glyph->u.notes.liquescentia) {
fprintf(f, " liquescentia %d (%s)\n",
glyph->u.notes.liquescentia,
gregorio_liquescentia_to_string(
glyph->u.notes.liquescentia));
}
break;
default:
/* not reachable unless there's a programming error */
/* LCOV_EXCL_START */
fprintf(f, " !!! NOT ALLOWED !!! %s\n",
gregorio_type_to_string(glyph->type));
break;
/* LCOV_EXCL_STOP */
}
if (glyph->type == GRE_GLYPH) {
for (note = glyph->u.notes.first_note; note;
note = note->next) {
fprintf(f, "- - - - - - - - - - - - - - - - - - - - - - - \n");
if (note->type) {
fprintf(f, " type %d (%s)\n",
note->type,
gregorio_type_to_string(note->type));
}
switch (note->type) {
case GRE_NOTE:
if (note->u.note.pitch) {
fprintf(f, " pitch %s\n",
dump_pitch(note->u.note.pitch,
score->highest_pitch));
}
if (note->u.note.shape) {
fprintf(f, " shape %d (%s)\n",
note->u.note.shape,
gregorio_shape_to_string(
note->u.note.shape));
}
if (note->u.note.is_cavum) {
fprintf(f, " is_cavum true\n");
}
if (note->u.note.liquescentia) {
fprintf(f, " liquescentia %d (%s)\n",
note->u.note.liquescentia,
gregorio_liquescentia_to_string(
note->u.note.liquescentia));
}
break;
default:
/* not reachable unless there's a programming error */
/* LCOV_EXCL_START */
fprintf(f, " !!! NOT ALLOWED !!! %s\n",
gregorio_type_to_string(note->type));
break;
/* LCOV_EXCL_STOP */
}
if (note->texverb) {
fprintf(f, " TeX string \"%s\"\n",
gregorio_texverb(note->texverb));
}
if (note->choral_sign) {
fprintf(f, " Choral Sign \"%s\"\n",
note->choral_sign);
}
if (note->signs) {
fprintf(f, " signs %d (%s)\n",
note->signs,
gregorio_sign_to_string(note->signs));
}
if (note->signs & _V_EPISEMA && note->v_episema_height) {
if (note->v_episema_height < note->u.note.pitch) {
fprintf(f, " v episema forced BELOW\n");
}
else {
fprintf(f, " v episema forced ABOVE\n");
}
}
if ((note->signs == _PUNCTUM_MORA
|| note->signs == _V_EPISEMA_PUNCTUM_MORA)
&& note->mora_vposition) {
fprintf(f, " mora vposition %s\n",
gregorio_vposition_to_string(note->
mora_vposition));
}
if (note->special_sign) {
fprintf(f, " special sign %d (%s)\n",
note->special_sign,
gregorio_sign_to_string(
note->special_sign));
}
if (note->h_episema_above == HEPISEMA_AUTO
&& note->h_episema_below == HEPISEMA_AUTO) {
fprintf(f, " auto hepisema size %d (%s)\n",
note->h_episema_above_size,
grehepisema_size_to_string(note->
h_episema_above_size));
fprintf(f, " auto hepisema bridge %s\n",
dump_bool(note->h_episema_above_connect));
}
else {
if (note->h_episema_above == HEPISEMA_FORCED) {
fprintf(f, " above hepisema size %d (%s)\n",
note->h_episema_above_size,
grehepisema_size_to_string(note->
h_episema_above_size));
fprintf(f, " above hepisema bridge %s\n",
dump_bool(note->h_episema_above_connect));
}
if (note->h_episema_below == HEPISEMA_FORCED) {
fprintf(f, " below hepisema size %d (%s)\n",
note->h_episema_below_size,
grehepisema_size_to_string(note->
h_episema_below_size));
fprintf(f, " below hepisema bridge %s\n",
dump_bool(note->h_episema_below_connect));
}
}
dump_hepisema_adjustment(f, note, SO_OVER, "above");
dump_hepisema_adjustment(f, note, SO_UNDER,
"below");
switch (note->high_ledger_specificity) {
case LEDGER_SUPPOSED:
break;
case LEDGER_EXPLICIT:
fprintf(f, " explicit high line %s\n",
dump_bool(note->high_ledger_line));
break;
case LEDGER_DRAWN:
fprintf(f, " drawn high line %s\n",
dump_bool(note->high_ledger_line));
break;
case LEDGER_EXPLICITLY_DRAWN:
fprintf(f, " forced drawn high line %s\n",
dump_bool(note->high_ledger_line));
break;
}
switch (note->low_ledger_specificity) {
case LEDGER_SUPPOSED:
break;
case LEDGER_EXPLICIT:
fprintf(f, " explicit low line %s\n",
dump_bool(note->low_ledger_line));
break;
case LEDGER_DRAWN:
fprintf(f, " drawn low line %s\n",
dump_bool(note->low_ledger_line));
break;
case LEDGER_EXPLICITLY_DRAWN:
fprintf(f, " forced drawn low line %s\n",
dump_bool(note->low_ledger_line));
break;
}
}
}
}
break;
default:
/* not reachable unless there's a programming error */
/* LCOV_EXCL_START */
fprintf(f, " !!! NOT ALLOWED !!! %s\n",
gregorio_type_to_string(element->type));
break;
/* LCOV_EXCL_STOP */
}
if (element->nabc_lines) {
fprintf(f, " nabc_lines %d\n",
(int)element->nabc_lines);
}
if (element->nabc_lines && element->nabc) {
for (i = 0; i < (int)element->nabc_lines; i++) {
if (element->nabc[i]) {
fprintf(f, " nabc_line %d \"%s\"\n",
(int)(i+1), element->nabc[i]);
}
}
}
}
fprintf(f, "=====================================================================\n");
}
}