                                 abcpp 1.4.5

                            Guido Gonzato, Ph.D.

Introduzione

   abcpp e' un preprocessore progettato per trattare i file ABC
   (http://abcnotation.com), e non solo quelli. Supporta l'output
   condizionale, macro, inclusione di file e consente di rinominare i
   simboli. L'ho scritto per due motivi: prima di tutto, volevo superare
   le incompatibilita' che ci sono tra diversi programmi per ABC; e poi
   volevo essere in grado di scrivere file ABC piu' portabili e leggibili.

   abcpp trae ispirazione dai preprocessori del C e di S-Lang
   (http://www.s-lang.org), e supporta varie direttive che permettono un
   po' di trucchi. Si scrive il file ABC con direttive come #define o
   #ifdef, definendo delle macro o escludendo parti di testo a seconda di
   determinate condizioni. Quindi, si preprocessa il file con abcpp,
   producendo un file di output adatto al particolare programma o voce. In
   breve, botte piena e moglie ubriaca!

   La home page di abcpp e altri programmi di utilita' per ABC e'
   http://abcplus.sourceforge.net.

Output condizionale

   Normalmente, se si scrive per una certa applicazione ABC si possono
   usare estensioni che altri programmi magari non supportano. Ad esempio,
   io scrivo soprattutto brani corali che poi converto con abcm2ps
   (http://moinejf.free.fr). abcm2ps supporta questo tipo di campo Q:
Q: "Allegro" 1/4 = 100

   e mi va bene, e' standard nella musica stampata. Pero', abc2midi
   (http://abc.sourceforge.net/abcMIDI) non accetta questa estensione, ma
   solo un campo Q: fatto cosi':
Q: 1/4 = 100

   Ci sono molte incompatibilita' come questa. Quindi, se volessi
   ascoltare il brano che ho scritto dovrei modificare il sorgente ABC!
   Non esiste...

   La soluzione e' usare direttive condizionali, come #ifdef... #else...
   #endif, per escludere parti che certe applicazioni non supportano:
#ifndef MIDI
Q: "Allegro" 1/4 = 100
#else
Q: 1/4 = 100
#endif

   L'output condizionale permette anche di estrarre parti di un brano:
#ifdef SOPRANO ALL
V: 1
...
#endif
#ifdef ALTO ALL
V: 2
...
#endif
#ifdef TENOR ALL
V: 3
...
#endif
#ifdef BASS ALL
V: 1
...
#endif

Macro

   Ho sempre pensato che i nomi delle decorazioni come !crescendo(! o
   !diminuendo(! sono troppo lunghi. Preferirei usare un equivalente piu'
   corto, diciamo !<(! o !>(!, ma nessuna applicazione ABC che io conosca
   supporta macro di questo tipo.

   La soluzione e' ridefinire i nomi delle decorazioni. Inoltre, usando le
   macro si possono ridefinire i nomi dei campi:
#define !<(! !crescendo(!
#define !<)! !crescendo)!
#define Title: T:
#define Composer: C:
#define System: %%staves
#ifdef MIDI
#define !x! z
#else
#define !x! x
#endif

Inclusione di file

   Non e' elegante riempire il sorgente ABC di definizioni di macro. E'
   meglio scriverle in un file esterno, quindi includerlo nel sorgente:
#include <fancyheader.abp>
#include "my own macros.abp"
     __________________________________________________________________

Installazione

   Scompattate l'archivio, date il comando 'make' e spostate abcpp in una
   directory nel $PATH. Suggerisco /usr/local/bin per i sistemi Unix,
   C:\WINDOWS per Windows 9x/ME.

Direttive supportate

   D'ora in avanti, <qualcosa> indica un argomento obbligatorio, mentre
   [qualcosa] un argomento opzionale.

   Le direttive devono iniziare alla colonna 1, e non appariranno
   nell'output. La corrente versione supporta le seguenti direttive:

   #
          usato per inserire commenti.

   #abc
          annulla la definizione delle note italiane; vedi #doremi

   #define <definizione> <sostituzione>''
          definisce una semplice macro (fino a 100); <sostituzione>
          sostituisce <definizione>. Le macro non si possono usare in
          definizioni successive; cioe', non si puo' fare

#define GU   Guido
#define GG   GU_Gonzato

          Le definizioni di una macro non possono contenere spazi, a meno
          che non vengano racchiuse tra virgolette. Se un carattere "
          (doppie virgolette) deve essere sostituito, precedetelo con un
          backslash: \". Lo stesso vale per il carattere backslash.

#define \"C \"^Do

          In alternativa, usate il carattere '~' dove dovrebbe apparire
          uno spazio. Ad esempio,

#define GG Guido~Gonzato
#define AMP "abcpp mi piace"

          espande 'GG' in 'Guido Gonzato', e AMP in "abcpp mi piace"
          (senza le virgolette). Se non mettete <sostituzione> e
          <definizione> esiste, la macro <definizione> verra' cancellata.
          Per esempio,

#define !lph! !longphrase!
...
#define !lph!

          annulla la definizione di !lph! e incrementa il numero di macro
          disponibili. Notate che non e' la stessa cosa di definire una
          macro vuota! Per definire una macro con una stringa vuota, si fa
          cosi':

      #define VUOTA ""

          Infine, per impedire una sostituzione di macro, si usa il
          carattere '\' per saltare la macro. Per esempio:

#define do c
#define re d
#define mi e
C: Gui\do, il \re dei \mi\mi

          non sostituisce le sillabe 'do 're' 'mi' nel campo C:.

   #doremi
          definisce le macro 'do', 're', 'mi', 'fa', 'sol', 'la', 'si'
          (anche le versioni in maiuscolo) che verranno sostituite da 'c',
          'd', 'e', 'f', 'g', 'a', 'b'.

   #ifdef <def1> [def2 def3 ...]
          le linee che seguono #ifdef, e prima del successivo #endif o
          #else, verranno preprocessate solo se almeno uno dei simboli e'
          definito. Non si possono annidare definizioni #ifdef, ed e'
          obbligatorio terminarle con #endif.

   #ifndef <def1> [def2 def3 ...]
          come #ifdef, ma la condizione e' valida se nessuno dei simboli
          e' definito. Non si possono annidare definizioni #ifndef, ed e'
          obbligatorio terminarle con #endif.

   #else
          stabilisce una condizione alternativa dopo #ifdef o #ifndef.

   #elifdef <def1> [def2 def3 ...]
          equivalente a #else seguito da #ifdef.

   #elifndef <def1> [def2 def3 ...]
          equivalente a #else seguito da #ifndef.

   #endif
          termina una condizione #ifdef o #ifndef.

   #include <filename> o "filename"
          preprocessa <filename> e lo include nell'output. Se il nome del
          file e' racchiuso tra <...>, abcpp cerca il file nella sua
          directory di libreria: C:\ABCPP sotto Windows, oppure
          /usr/share/abcpp sotto Unix.

   #undefine
          sospende la sostituzione delle macro per le linee seguenti.

   #redefine
          riprende la sostituzione delle macro.
     __________________________________________________________________

Uso

   abcpp e' un programma a linea di comando. Si usa in questo modo:
$ abcpp [-s] [-c] [-h] [-def1 -def2 ...] [inputfile] [outputfile]

   -s
          toglie all'input le decorazioni e le linee w:

   -c
          toglie all'input gli accordi di accompagnamento

   -p
          cambia gli accordi delimitati da '+' in accordi delimitati da
          '[]'

   -h
          mostra un aiuto

Esempio 1: Macro e condizionali

   Il brano ABC che segue contiene direttive per creare diversi header, a
   soconda che il simbolo MIDI sia definito o no. Alcuni simboli e
   decorazioni sono ridefiniti per creare un look alla M-Tx:
% my_music.abp
%
#define Index:  X:
#define Title:  T:
#define Meter:  M:
#define Length: L:
#define Tempo:  Q:
#define Voice:  V:
#define Key:    K:
#define Style:  %%staves
#define Duet    [1~2]
#define !<(!  !crescendo(!
#define !<)!  !crescendo)!
#define !>(!  !diminuendo(!
#define !>)!  !diminuendo)!
#define !H!   !fermata!
Index: 1
Title: ABCPP test
Meter: 4/4
Length: 1/4
#ifdef MIDI
Tempo: 1/4 = 80
#else
Tempo: "Allegro"
Voice: 1 clef=treble name="Flute"
Voice: 2 clef=treble name="Violin"
Style: Duet
#endif
Key: C
%
Voice: 1
cdef|!<(!cde!<)!f|!>(!CDE!>)!F|!H!G4|
Voice: 2
ccee|ccgg        |g f e d     |!H!C4|
%
% End of file my_music.abp

   Non e' male, ma si puo' fare di meglio. Scriviamo un file chiamato
   my_defines.abp, con scritto:
# my_defines.abp
#
#define Index:  X:
#define Title:  T:
#define Meter:  M:
#define Length: L:
#define Tempo:  Q:
#define Voice:  V:
#define Key:    K:
#define Style:  %%staves
#define Duet    [1~2]
#define !<(!  !crescendo(!
#define !<)!  !crescendo)!
#define !>(!  !diminuendo(!
#define !>)!  !diminuendo)!
#define !H!   !fermata!

   Ora riscriviamo my_music.abp:
% my_music.abp
%
#
#include my_defines.abp
#
Index: 1
Title: ABCPP test
Meter: 4/4
Length: 1/4
#ifdef MIDI
Tempo: 1/4 = 80
#else
Tempo: "Allegro"
Voice: 1 clef=treble name="Flute"
Voice: 2 clef=treble name="Violin"
Style: Duet
#endif
Key: C
%
Voice: 1
cdef|!<(!cde!<)!f|!>(!CDE!>)!F|!H!G4|
Voice: 2
ccee|ccgg        |g f e d     |!H!C4|
%
% End of file my_music.abp

   Vi piace cosi'? A me sembra molto piu' leggibile. Siamo pronti per
   preprocessare my_music.abp con abcpp:
$ abcpp my_music.abp my_music_nomidi.abc
$ abcpp -MIDI my_music.abp my_music_midi.abc

   La prima linea non definisce alcun simbolo, mentre la seconda definisce
   il simbolo MIDI. Quest'ultimo viene usato per produrre un header
   alternativo. Otteniamo quindi due file ABC: uno per la stampa, l'altro
   per fare un file midi.

   Se non ve ne siete accorti, notate che ho usato l'estensione .abp per i
   file ABC con direttive abcpp.

Esempio 2: note italiane

   In Italia, le note vengono scritte con la notazione di Guido d'Arezzo:
   do re mi fa sol la si -> c d e f g a b. Utilizzando alcune macro
   predefinite e un po' di attenzione, potrete scrivere file ABC usando do
   re mi... invece delle note anglosassoni. Pero' tale sostituzione non
   deve avvenire nelle linee w:.

   Scriviamo un semplice brano:
% doremi.abp
#doremi
X: 1
T: Do \re \mi -> c d e
C: Gui\do
M: 4/4
L: 1/4
Q: 1/4 = 100
K: C
%
#define !tieni! !fermata!
DO RE MI FA|SOL LA SI !tieni!do|do SI LA SOL|FA MI RE DO|
#abc
w: do re mi fa sol la si do, do si la sol fa mi re do.
#doremi
DO RE MI FA|SOL LA SI !tieni!do|do SI LA SOL|FA MI RE DO|
#abc
w: do re mi fa sol la si do, do si la sol fa mi re do.
%
% End of file doremi.abp

   Che ne dite? Questo trucchetto consente di scrivere file ABC anche a
   chi non ha dimestichezza con le note in notazione anglosassone
   (studenti...). Notate che le sillabe nell'header iniziano con '\':
   questo per impedire che vengano sostituite dalla loro definizione.

Esempio 3: estrazione di parti

   Il file ABC seguente e' scritto per SATB. Vediamo come fare per
   ottenere quattro diversi file ABC, uno per voce:
X: 1
T: Part extraction
C: Guido Gonzato
M: 4/4
L: 1/4
Q: 1/4 = 60
%%staves [S A T B]
V: S clef=treble name="Soprano" sname="S"
V: A clef=treble name="Alto"    sname="A"
V: T clef=treble name="Tenor"   sname="T"
V: B clef=bass   name="Bass"    sname="B"
K: C
%
#ifdef SOPRANO ALL
[V: S] cccc|eeee|gggg|c'c'c'c'|
#endif
#ifdef ALTO ALL
[V: A] cccc|GGGG|cccc|eeee|
#endif
#ifdef TENOR ALL
[V: T] CCCC|EEEE|GGGG|cccc|
#endif
#ifdef BASS ALL
[V: B] CCCC|G,G,G,G,|CCCC|EEEE|
#endif
%

   Create i quattro file con questi comandi:
$ abcpp -SOPRANO parts-soprano.abc
$ abcpp -ALTO parts-alto.abc
$ abcpp -TENOR parts-tenor.abc
$ abcpp -BASS parts-bass.abc

   e il brano completo con:
$ abcpp -ALL parts.abc parts-all.abc

   Normalmente, per estrarre le parti sara' meglio usare il programma
   abc2prt; vedete alla home page.

+ Esempio 4: Accordi in italiano

   Come e' noto, gli accordi di accompagnamento in ABC sono definiti solo
   con le note anglosassoni. Se volete stamparli con le note italiane,
   ecco come si puo' fare:
% doremi.abp
#ifndef MIDI
#define \"C\" \"^Do\"
#define \"G\" \"^Sol\"
#endif
X: 1
T: do re mi
M: 4/4
L: 1/4
K: C
%
"C"CDEF|"G"GABc|"C"C2"G"G2|"C"C2z2|
     __________________________________________________________________

Altre caratteristiche

Opzioni di linea di comando

   -s
          questa opzione toglie tutte le linee w: e le decorazioni. Puo'
          servire per quelle applicazioni ABC che seguono il vecchio
          standard 1.6.

   -c
          toglie tutti gli accordi di accompagnamento. In molti file ABC,
          gli "accordi di accompagnamento" sono in realta' delle
          annotazioni testuali. abc2midi cerchera' di suonarli, ovviamente
          con orribili risultati; meglio toglierli.

   -p
          cambia gli accordi delimitati da '+' in accordi delimitati da ''
          e ''

   -b
          toglie i '!' singoli (estensione abc2win per forzare una nuova
          linea).

   -k
          sostituisce i '!' singoli con !break!.

   -h
          mostra l'help.

Disabilitare le macro

   Le definizioni di macro possono interferire l'una con l'altra. Per
   impedire una sostituzione in certi punti, usate il carattere '\'. Ad
   esempio, se la sillaba 'do' viene #definita come 'c', la parola 'Guido'
   diventera' 'Guic', ma 'Gui\do' diventera' 'Guido'.

Limitazioni

    1. possono esserci fino a 20 definizioni nella linea di comando.
    2. una direttiva puo' contenere fino a 20 simboli.
    3. la lunghezza di un simbolo va da 0 a 50 caratteri.
    4. possono esserci fino a 100 macro.
    5. le definizioni di macro possono interferire l'una con l'altra.

   Prima o poi trovero' il tempo di cambiare tutte le strutture statiche
   di abcpp con equivalenti dinamiche.
     __________________________________________________________________

Da fare...

    1. se -s e' attiva, togliere anche le linee con simboli ridefiniti con
       U:
    2. una versione grafica con Fltk (http://www.fltk.org)
    3. implementare il campo 'Dyn:' per aggiungere una linea di dinamica
       che si fonde con la prossima linea (reso superfluo dal campo d: di
       abcm2ps)
    4. la stessa cosa, con il campo 'Text:'
    5. suggerimenti?

Copyright e Licenza
     __________________________________________________________________

   abcpp e' copyright di Guido Gonzato <guido.gonzato at gmail.com>
   2001-2012, e viene rilasciato sotto la General Public Licence. Se
   trovate che questo programma sia utile, o trovate degli errori, o avete
   critiche o suggerimenti, scrivetemi. abcpp mi e' molto utile, spero che
   possa essere utile anche ad altre persone.

   Ciao,

   Guido =8-)
     __________________________________________________________________

                              This document was generated using AFT v5.097
