205.3 Gestione delle sessioni
Transcript
205.3 Gestione delle sessioni
Introduzione a NOS-KA9Q -- IPv4 per Dos 2235 205.2.4 Comando domain Il comando ‘domain’ permette di definire quali sono i servizi DNS a cui il sistema NOS può rivolgersi; permette anche di configurare il loro utilizzo e di definire eventualmente una risoluzione locale per alcuni indirizzi. Qui viene mostrato solo come dichiarare l’uso dei servizi DNS e il dominio predefinito. domain addserver indirizzo_ip_DNS domain suffix [suffisso_predefinito ] Segue la descrizione di alcuni esempi. • domain addserver 192.168.1.1 domain addserver 192.168.1.2 Dichiara l’uso del servizio DNS collocato presso i nodi 192.168.1.1 e 192.168.1.2. • domain suffix brot.dg. • Dichiara che in caso di nomi di dominio incompleti viene aggiunto il suffisso brot.dg. domain suffix Mostra il suffisso predefinito per i nomi di dominio. 205.3 Gestione delle sessioni Il sistema NOS può gestire diverse sessioni di lavoro, corrispondenti ad altrettante attività che implicano l’instaurarsi di una connessione. Per esempio si possono gestire diverse connessioni TELNET simultaneamente e lo stesso vale per l’utilizzo del protocollo FTP. Tutto questo funziona in modo paragonabile al sistema delle console virtuali di GNU/Linux: con il sistema NOS c’è una finestra per la modalità di comando, dove si trova l’invito, attraverso la quale si impartiscono i comandi, e le finestre delle sessioni che vengono aperte automaticamente in base al tipo di comando che viene dato. Quando ci si trova a interagire con una sessione è possibile tornare alla finestra della modalità di comando attraverso il tasto [ F10 ] (vale solo per il NOS che si basa sul Dos) e poi, da lì è possibile tornare a una sessione attraverso il comando ‘session’. Da questo si comprende che le sessioni sono numerate, cosa che avviene in modo automatico. Una di queste è anche la sessione attiva, ovvero quella a cui si potrebbe fare riferimento quando non se ne specifica il numero. Comando session [n_sessione] session session 1 close [n_sessione] close close 1 reset [n_sessione] Descrizione Il comando ‘session’ permette di tornare a una sessione ancora attiva, specificandone il numero. Se questo non viene indicato, si ottiene l’elenco delle sessioni esistenti. Elenca le sessioni esistenti. Torna alla prima sessione. Il comando ‘close’ interrompere una connessione TCP attraverso l’invio di un pacchetto FIN (che serve a chiudere una connessione del genere). Il risultato che si ottiene di solito è che la sessione corrispondente termina. Interrompe la connessione della sessione corrente. Interrompe la connessione della prima sessione. Il comando ‘reset’ interrompere una connessione TCP attraverso l’invio di un pacchetto RST. Il risultato che si vuole ottenere è la conclusione della sessione corrispondente, ma dal momento che il metodo dell’invio di un pacchetto RST non garantisce l’ottenimento di ciò, sarebbe preferibile utilizzare il comando ‘close’ al suo posto. Introduzione a NOS-KA9Q -- IPv4 per Dos 2236 Comando abort [n_sessione] abort abort 1 Descrizione Il comando ‘abort’ permette di interrompere un’operazione di carico o scarico dati attraverso una sessione FTP. La sessione in questione non viene chiusa.< Interrompe le operazioni di carico-scarico nella sessione corrente, purché di FTP. Interrompe le operazioni di carico-scarico nella prima sessione, purché sia di FTP. 205.4 Attività nel sistema locale Dal momento che non è possibile intervenire direttamente sul sistema operativo sottostante senza interrompere le connessioni che eventualmente fossero state instaurate, NOS deve incorporare alcune funzionalità che non hanno attinenza con la rete, ma che sono indispensabili a livello pratico. Per quanto riguarda i percorsi delle directory possono essere indicati utilizzando sia le barre oblique inverse (‘\’) che quelle normali (‘/’) per la separazione dei nomi che li compongono. Comando cd [percorso] pwd [percorso] mkdir [percorso] rmdir [percorso] dir more file ... rename file_origine file_destinazione delete file ... ! | shell Descrizione Permette di cambiare la directory corrente nel sistema sottostante. Se viene utilizzato senza l’indicazione del percorso, si ottiene la visualizzazione della directory corrente. Mostra quale sia la directory corrente. Elenca il contenuto della directory corrente. Crea una directory nel sistema operativo sottostante. Elimina una directory nel sistema operativo sottostante. Scorre il testo di uno o più file del sistema operativo sottostante, facendo una pausa tra le schermate. Rinomina o sposta un file del sistema operativo sottostante. Elimina i file indicati negli argomenti dal sistema operativo sottostante. Sospende il funzionamento di NOS per aprire una shell del sistema operativo sottostante (‘COMMAND.COM’). 205.5 Gestione della rete e delle connessioni Oltre a quanto visto inizialmente per ciò che riguarda la definizione delle interfacce, la loro configurazione, l’instradamento e la risoluzione dei nomi, ci sono una serie di comandi e di funzionalità per la gestione della rete. 205.5.1 Indirizzi IP e indirizzi MAC arp arp flush Il comando ‘arp’ permette di conoscere il contenuto della tabella di trasformazione degli indirizzi IP in indirizzi fisici e viceversa. Questa viene costruita automaticamente dal sistema, durante il suo funzionamento. Sono disponibili degli argomenti particolari per inserire a forza delle voci nella tabella, anche se questa operazione non dovrebbe essere necessaria. In particolare, il comando ‘arp flush’ svuota la tabella attuale, costringendo il sistema NOS a ricominciare a costruirsela. Introduzione a NOS-KA9Q -- IPv4 per Dos 2237 205.5.2 Ping e instradamento Attraverso il comando ‘ping’ si può inviare una richiesta di eco utilizzando il protocollo ICMP. Questo è il modo consueto per verificare che sia presente un certo nodo nella rete. In generale conviene utilizzare soltanto la sintassi seguente, con la quale viene inviata un’unica richiesta. ping host Per verificare il percorso dei pacchetti lungo la rete si può utilizzare il comando ‘hop’. Il comando normale si articola nel modo seguente: hop check host Tuttavia, si può intervenire su alcuni parametri di funzionamento di questo comando: il TTL (Time to live), hop maxttl max_salti l’attesa massima, hop maxwait n_secondi e il numero di pacchetti di prova che vengono inviati a ogni nodo. hop queries n_pacchetti Infine, è possibile abilitare o meno la visualizzazione di informazioni aggiuntive: hop trace [on|off] 205.5.3 Varie hostname [nome] Attraverso il comando ‘hostname’ è possibile definire o visualizzare il nome attribuito al nodo. Questo dovrebbe corrispondere alla parte finale del nome di dominio, ma in ogni caso serve solo nei messaggi di presentazione del sistema. socket [n_porta] Attraverso il comando ‘socket’ è possibile conoscere lo stato delle porte. Utilizzandolo senza argomenti si ottiene l’elenco delle porte utilizzate, generalmente quelle dei servizi in ascolto ed eventualmente anche quelle gestite dalle sessioni in cui si utilizzano dei clienti di qualche tipo, mentre specificando una porta precisa si ottengono le statistiche sul traffico intrattenuto. 205.6 NOS come cliente L’uso più importante del sistema NOS è quello di cliente in grado di utilizzare i servizi fondamentali di una rete TCP/IP. Si tratta principalmente di TELNET e FTP. 205.6.1 Cliente TELNET Il sistema NOS permette di attivare una sessione TELNET verso un altro sistema che offra la possibilità di accedere attraverso questo tipo di protocollo. Purtroppo, il tipo di terminale corrispondente alla sessione TELNET è molto modesto, tanto che nelle versioni più limitate di NOS non si possono usare nemmeno i tasti freccia. Introduzione a NOS-KA9Q -- IPv4 per Dos 2238 telnet host Quando si utilizza questo tipo di cliente TELNET per accedere a un nodo corrispondente a un elaboratore GNU/Linux, il tipo di terminale che si vede nella variabile ‘TERM’ è ‘network’, che però non corrisponde ad alcuna voce nel sistema Terminfo o nel sistema Termcap. Eventualmente si può cambiare questo nome con ‘ansi’, o ‘ansi-mono’ se si preferisce. Da una sessione TELNET è possibile tornare alla modalità di comando premendo il tasto [ F10 ]. Per ritornare alla sessione con TELNET, si potrà poi utilizzare il comando ‘session’. 205.6.2 Cliente FTP Il sistema NOS permette di attivare una sessione FTP. Una volta avviata, si ha a disposizione un cliente FTP tradizionale, con comandi molto simili a quelli del programma ‘ftp’ dei sistemi Unix (se ne trova la descrizione nel capitolo 148). ftp host L’unico vero difetto sta nel sistema operativo sottostante: utilizzando il Dos i nomi dei file che vengono salvati sono ridotti al modello «8.3». È importante ricordare di modificare sempre il tipo di trasferimento dati, in modo che sia di tipo binario (image): ‘type i’. 205.7 NOS come servente I servizi offerti da NOS sono limitati e comunque dipendono dalla versione di questo sistema. Questi servizi devono essere abilitati attraverso il comando ‘start’. Dal momento che dipende dalla versione di NOS se un tipo di servizio è disponibile o meno, attraverso il comando ‘start ?’ si ottiene l’elenco di questi. In generale non conviene avere grandi pretese; probabilmente è il caso di attivare sempre i servizi ‘discard’, ‘echo’, ‘ftp’ e ‘finger’ (ammesso che questo ultimo possa avere senso). start start start start discard echo finger ftp Per converso, volendo disattivare un servizio basta utilizzare il comando ‘stop’ nello stesso modo. 205.7.1 Registrazione degli eventi NOS permette di annotare gli accessi in un registro abbastanza semplificato. Si attiva questa funzionalità attraverso il comando ‘log’: log [stop | file_delle_registrazioni ] Per esempio, per attivare la registrazione degli accessi nel file ‘C:\ACCESSI.LOG’, si può usare il comando seguente: log c:\accessi.log Introduzione a NOS-KA9Q -- IPv4 per Dos 2239 Come si può intuire, il comando ‘log stop’ termina l’attività di registrazione degli accessi, senza interferire con gli accessi stessi. Infine, il comando ‘log’ senza argomenti permette di sapere se questo sia attivo e in tal caso su quale file vengono fatte le annotazioni. 2240 Introduzione a NOS-KA9Q -- IPv4 per Dos 205.7.2 Servente FTP Per abilitare il servizio FTP, oltre che usare il comando ‘start ftp’, occorre predisporre un file di autorizzazioni: ‘ftpusers’ collocato nella directory radice del servizio NOS. Il file deve contenere delle righe scomposte in quattro campi separati da uno o più spazi e si possono indicare anche dei commenti che si introducono con il simbolo ‘#’. utente parola_d’ordine percorso permessi I quattro campi sono obbligatori e il significato è intuitivo: 1. utente serve a specificare il nome dell’utente che può accedere; 2. parola_d’ordine rappresenta la parola d’ordine in chiaro necessaria per l’accesso -- se si utilizza un asterisco (‘*’), viene accettata qualunque parola d’ordine; 3. percorso indica la directory a partire dalla quale si concede l’accesso all’utente; 4. permessi è un numero che esprime i permessi consentiti all’utente. I permessi non sono indicati secondo la tradizione Unix, quindi occorre fare attenzione. I permessi sono espressi con un solo numero ottenuto sommandone altri, che comunque si riferiscono alla directory di partenza e a tutte le sottodirectory: uno rappresenta un permesso di lettura; due rappresenta un permesso di creazione (di aggiunta di file senza poter sovrascrivere o eliminare quelli esistenti); quattro rappresenta un permesso di scrittura (o di sovrascrittura). Si osservi l’esempio seguente: tizio tazza \home\tizio 7 caio capperi \home\caio 7 semproni sempre \progetto 3 ftp * \pub 1 anonymous * \pub 1 Gli utenti ‘tizio’ e ‘caio’ hanno una loro directory personale in cui possono fare quello che vogliono; l’utente ‘semproni’ partecipa a un lavoro che si trova nella directory ‘\PROGETTO\’ e lì ha la possibilità di immettere file, senza cancellare o sovrascrivere quelli presenti. Infine, gli utenti ‘ftp’ e ‘anonymous’ accedono con una parola d’ordine qualunque alla directory ‘\PUB\’, con il solo permesso di lettura. 205.8 NOS come router IPv4 NOS funziona perfettamente come router se l’elaboratore in cui si utilizza dispone di più interfacce di rete. A titolo di esempio viene mostrato in che modo potrebbero essere utilizzate due schede di rete compatibili NE2000. Supponendo che queste utilizzino rispettivamente le risorse IRQ 10, I/O 28016, e IRQ 11, I/O 30016, la configurazione del driver di pacchetto (si fa riferimento a quanto descritto nella sezione 203.1) potrebbe essere quella seguente: NE2000 0x60 0x0a 0x280 NE2000 0x61 0x0b 0x300 Supponendo che queste due schede servano a connettere le reti 192.168.1. e 192.168.2. , supponendo anche che l’instradamento predefinito passi per il router 192.168.1.254, il file di configurazione di NOS potrebbe contenere in particolare le righe seguenti: * # Configurazione delle interfacce di rete. attach packet 0x60 ethernet0 8 1500 * Introduzione a NOS-KA9Q -- IPv4 per Dos 2241 attach packet 0x61 ethernet1 8 1500 # Definizione degli indirizzi IP. ifconfig ethernet0 ipaddress 192.168.1.10 ifconfig ethernet0 netmask 255.255.255.0 ifconfig ethernet1 ipaddress 192.168.2.10 ifconfig ethernet1 netmask 255.255.255.0 # Instradamento. route add 192.168.1.0/24 ethernet0 route add 192.168.2.0/24 ethernet1 route add default ethernet0 192.168.1.254 Non c’è bisogno di fare altro: l’attraversamento dei pacchetti da un’interfaccia all’altra avviene automaticamente (purché gli instradamenti siano corretti). Appunti di informatica libera 2003.01.01 --- Copyright © 2000-2003 Daniele Giacomini -- daniele @ swlibero.org 2242 Introduzione a NOS-KA9Q -- IPv4 per Dos Parte xxxix Samba di Fulvio Ferroni fuferro @ tin.it 2243 Copyright © Fulvio Ferroni fuferro @ tin.it Via Longarone, 6 - 31030 - Casier (TV) Fulvio Ferroni ha concesso l’inclusione del suo documento alle stesse condizioni dell’opera complessiva. 2244 206 Informazioni generali su Samba . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2246 206.1 Natura di Samba . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2246 206.2 Componenti di Samba . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2246 207 Servente Samba . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2248 207.1 I demoni del servente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2248 207.2 Attivazione del servente Samba . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2248 207.3 Configurazione di un servente Samba . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2248 207.4 Programmi ausiliari per un servente Samba . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2257 208 Samba dal lato cliente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2259 208.1 smbclient . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2259 208.2 smbmount . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2259 208.3 Uso con Samba di stampanti MS-Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2260 208.4 Altri strumenti utili . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2260 209 Samba come servente WINS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2261 210 Samba e la scansione della rete . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2262 211 Autenticazione di utenti MS-Windows con Samba . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2264 211.1 Domain logons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2265 211.2 Logon script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2265 211.3 Logon path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2265 211.4 Logon home e logon drive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2266 211.5 Sezione [netlogon] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2266 211.6 Definizione delle utenze per macchina . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2266 212 Accesso a GNU/Linux da parte di utenti di un dominio MS-Windows con Winbind 2267 212.1 Configurazioni necessarie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2267 212.2 Attivazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2269 213 Samba e DFS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2270 2245 Capitolo 206 Informazioni generali su Samba Samba 1 è un insieme di strumenti realizzati da Andrew Tridgell per le piattaforme Unix e GNU/Linux, distribuito sotto licenza GNU GPL, curato da un piccolo gruppo di persone di varie parti del mondo coordinate dallo stesso Tridgell. 206.1 Natura di Samba Samba utilizza il protocollo SMB (Server message block) definito per reti MS-Windows e a sua volta basato sull’interfaccia di rete NetBIOS (Network basic input output system). SMB è stato progettato originariamente per reti molto piccole. Per permettere la connessione a reti più estese ed eterogenee, Microsoft ha sviluppato il sistema CIFS (Common internet file system) ancora basato su NetBIOS. Samba può essere a tutti gli effetti considerato una versione libera e gratuita di CIFS; con esso, una macchina GNU/Linux, può accedere alle risorse condivise di un elaboratore MS-Windows ma anche mettere a disposizione proprie risorse a clienti MS-Windows o GNU/Linux. Più in dettaglio ecco quali sono i servizi offerti da Samba: • servente per offrire la condivisione di file system e stampanti; • cliente per l’accesso a risorse NetBIOS su macchine Unix, MS-Windows, Novell remote; • master browser sia locale che di dominio; • servente WINS (Windows internet name service); • servente per l’autenticazione di clienti di un dominio MS-Windows; • servente DFS (Distributed file system). A livello di protocolli è necessario far presente che MS-Windows può incapsulare messaggi SMB sui protocolli IPX/SPX, NetBEUI e TCP/IP mentre invece Samba può dialogare con macchine MS-Windows solo attraverso il TCP/IP. Questa non è comunque una grande limitazione vista la diffusione ormai universale di tale protocollo La descrizione di come NetBIOS debba operare all’interno di una rete TCP/UDP è contenuta nei documenti RFC 1001/1002. Lo standard descritto in questi documenti è noto come NBT (NetBIOS over TCP/IP) ed è alla base del funzionamento sia delle reti NetBIOS che di Samba. 206.2 Componenti di Samba La versione di Samba che viene presa in esame è la 2.2 cioè la più recente al momento della stesura di questi appunti (primavera 2002). I pacchetti da installare sono (si fa riferimento a pacchetti RPM essendo le prove state effettuate su macchine dotate di una distribuzione GNU/Linux Red Hat; x.y.z rappresenta il numero di versione): • ‘samba-x.y.z .i386.rpm’ 1 Samba GNU GPL 2246 Informazioni generali su Samba 2247 • ‘samba-client-x.y.z .i386.rpm’ • ‘samba-common-x.y.z .i386.rpm’ Il primo pacchetto contiene gli strumenti lato servente di Samba, il secondo gli strumenti lato cliente, il terzo una serie di file indispensabili per il funzionamento sia del servente che del cliente. Scendendo più in dettaglio: • nel pacchetto ‘samba’ si trovano i demoni ‘nmbd’ e ‘smbd’ che sono alla base del funzionamento di un servente Samba e alcuni programmi di servizio come ‘smbadduser’, ‘smbstatus’; • nel pacchetto ‘samba-client’ sono contenuti altri programmi di servizio come ‘nmblookup’, ‘smbclient’, ‘smbmount’, ‘smbumount’, ‘smbtar’, ‘findsmb’, ‘testparm’; • nel pacchetto ‘samba-common’ si trovano tra altri elementi il programma ‘smbpasswd’ e il file di configurazione di Samba ‘/etc/samba/smb.conf’ precompilato con alcune impostazioni predefinite. Tutti questi elementi verranno trattati nel seguito di questo documento. Capitolo 207 Servente Samba 207.1 I demoni del servente Un servente Samba si basa su due demoni:1 • ‘smbd’ che fornisce i servizi di condivisione di file stampanti per i clienti SMB (che possono essere macchine MS-Windows o altre macchine GNU/Linux) e si occupa della gestione delle sessioni di comunicazione e delle autenticazioni necessarie all’accesso alle risorse che vengono offerte in condivisione dal servente; il demone avvia una copia di se stesso per ogni richiesta di servizio da soddisfare; • ‘nmbd’ che gestisce la distribuzione dell’elenco delle risorse condivise alle altre macchine della rete, può mantenere la lista delle risorse condivise (scansione della rete) ed eventualmente risolvere i nomi NetBIOS della rete (servente WINS); 207.2 Attivazione del servente Samba Entrambi i demoni ‘smbd’ e ‘nmbd’ possono essere attivati in modo autonomo, o gestiti dal supervisore dei servizi di rete (come Xinetd); qui viene presa in esame solo la prima alternativa che è di gran lunga la più praticata e anche quella predefinita in molte distribuzioni GNU/Linux. In quasi tutte le distribuzioni si trovano infatti degli script preconfezionati per l’attivazione e la disattivazione di determinati servizi; nel caso della Red Hat si attivano entrambi i demoni con il comando: # /etc/rc.d/init.d/smb start e si disattivano con il comando: # /etc/rc.d/init.d/smb stop ci sono poi anche i comandi: # /etc/rc.d/init.d/smb restart e # /etc/rc.d/init.d/smb status il cui significato dovrebbe essere ovvio. 207.3 Configurazione di un servente Samba La configurazione di un servente Samba si basa su di un file di testo; nella distribuzione Red Hat (ma anche per altre) è ‘/etc/samba/smb.conf’. Solitamente viene fornito preconfezionato e commentato, con una configurazione di base già pronta all’uso; ovviamente è possibile intervenire sul file per adattare il comportamento del servente alle proprie esigenze. Prima di esaminare la struttura del file e i parametri principali di configurazione è opportuno sottolineare alcuni importanti aspetti generali: 1 Un demone è un programma di servizio costantemente in esecuzione e pronto a rispondere a richieste a esso rivolte da altri processi in esecuzione localmente o da una posizione remota 2248 Servente Samba 2249 • È indifferente usare maiuscole o minuscole a meno che tale uso non vada a interferire con le regole del sistema operativo sottostante. Se ad esempio si indica il percorso di una directory condivisa su una macchina GNU/Linux con l’opzione (che verrà descritta più avanti) ‘PATH=/USR/LOCAL’, Samba non ha alcun problema ad accettare la direttiva ma al momento di collegarsi alla risorsa fallisce in quanto in GNU/Linux quella directory al 99 % non esiste, mentre esiste ‘/usr/local/’. È quindi consigliabile l’uso delle minuscole. • Le righe di commento iniziano con i simboli ‘;’ oppure ‘#’. • Il carattere di continuazione riga è ‘\’. • Alcune direttive di configurazione di Samba, per ragioni di compatibilità, sono ridondanti; per questo motivo uno stesso risultato si può ottenere in modi diversi. • Per rendere effettive le variazioni fatte al file di configurazione non è necessario riavviare i demoni di Samba in quanto il file viene riletto automaticamente ogni 60 s; se si vuole forzare la rilettura basta impartire il comando: ‘kill -SIGHUP n ’ dove n è il numero del processo corrispondente al demone ‘smbd’ in funzione (per individuarlo si può eseguire ‘ps afx | grep smbd’). Occorre comunque notare che non tutti i cambiamenti alla configurazioni vengono necessariamente attuati subito; in particolare le variazioni della configurazione di risorse condivise rimangono congelate finché c’è qualche utente connesso a tali risorse. Il file di configurazione è suddiviso in sezioni i cui nomi sono racchiusi tra parentesi quadrate. Ogni sezione corrisponde a una risorsa condivisa a eccezione della sezione ‘global’ usata per le configurazioni globali. Altre sezioni con un ruolo un po’ particolare sono ‘homes’ e ‘printers’. Sezione [global] In essa si impostano le informazioni che condizionano tutto il sistema ed eventualmente quei parametri che se non specificati vengono assunti in modo predefinito, ad esempio il nome del gruppo di lavoro (workgroup). Sezione [homes] In essa si regolano i parametri di configurazione delle directory personali degli utenti che si collegano al servente Samba. Sezione [printers] Consente di impostare le caratteristiche della condivisione di tutte le stampanti installate nella macchina GNU/Linux senza dover definire una condivisione separata per ognuna di esse. All’interno del file di configurazione è possibile usare alcune variabili il cui nome viene sostituito dal rispettivo valore quando il file di configurazione viene utilizzato dai demoni ‘smbd’ e ‘nmbd’. Segue una lista delle variabili più importanti con una breve descrizione: Variabile %S %P %u %g %U %D %G %H Descrizione nome del servizio corrente (‘[tmp]’, ‘[homes]’, ecc.); directory principale del servizio corrente; nome dell’utente (GNU/Linux) del servizio corrente; nome del gruppo primario di ‘%u’; nominativo-utente della sessione; nome del dominio MS-Windows in cui il servente Samba si integra; nome del gruppo primario di ‘%U’; directory personale assegnata a ‘%u’; Servente Samba 2250 Variabile %v %h %m %L %M %N %p %d %a %I %T Descrizione versione in uso di Samba; nome del nodo che ha avviato il servizio Samba; nome NetBIOS della macchina cliente; nome NetBIOS assegnato al servente; nome Internet della macchina cliente; nome della directory personale ottenuta dal servizio NIS del servente; percorso della directory personale ottenuto dal servizio NIS; numero identificativo del processo corrente; architettura software della macchina remota (Samba, MS-Windows 95/98/Me/NT), diversamente sarà assegnata la parola ‘UNKNOWN’; indirizzo IP della macchina cliente; data e ora corrente. 207.3.1 smb.conf: sezione global È la sezione che appare in tutte le configurazioni di Samba, anche se non è obbligatoria. Le opzioni in essa contenute vengono applicate a tutte le altre sezioni. Viene mostrato un esempio comprendente alcune direttive di uso comune suddivise in blocchi in base alla funzione svolta e intervallate da brevi descrizioni del loro significato: [global] # # identificazione del servente # workgroup = INF netbios name = pippo server string = Samba Server La voce più importante è ‘workgroup’ che assegna a Samba il dominio o il gruppo di appartenenza. Occorre assegnarla correttamente, pena conflitti nella rete paritetica (peer-to-peer). La voce ‘netbios name’ è di utilizzo meno frequente e serve ad assegnare al servente Samba un nome NetBIOS a piacere. Il nome NetBIOS viene infatti assegnato in modo definito pari a quello ottenuto dal DNS. Ad esempio se il nome DNS del servente fosse muscolis.inf.besta il nome NetBIOS sarebbe ‘muscolis’. Uno dei casi in cui è utile poter impostare un nome NetBIOS diverso da quello predefinito è quello in cui la rete è suddivisa in due o più domini DNS diversi; in questo caso potrebbe infatti anche esistere una macchina con nome muscolis.mat.besta che verrebbe quindi ad avere lo stesso nome NetBIOS. Ovviamente il valore di ‘netbios name’ deve essere assegnato seguendo le regole dei nomi NetBIOS (unica stringa senza punti contenente i simboli alfabetici maiuscoli e minuscoli le cifre e i simboli ‘!’, ‘@’, ‘#’, ‘$’, ‘%’, ‘^’, ‘&’, ‘(’, ‘)’, ‘-’, ‘’’ e ‘~’). Con ‘server string’ si assegna semplicemente la descrizione dell’elaboratore servente. # # opzioni di rete # hosts allow = 192.168.1. localhost hosts deny = 172.16.244.254 interfaces = 192.168.1.1/24 172.16.244.1/16 bind interfaces only = yes Le direttive ‘Host allow’ e ‘host deny’ servono rispettivamente a specificare quali nodi possono e non possono accedere alle risorse condivise dal servente Samba. L’indicazione può essere fatta tramite il nome del nodo, il nome di dominio, il numero IP, il numero della sottorete. Nell’esempio viene concesso l’accesso a tutte le macchine della sottorete 192.168.1. e * Servente Samba 2251 al localhost (è opportuno che l’accesso a localhost sia sempre concesso pena possibili malfunzionamenti della scansione delle risorse del servente) e viene negato alla macchina con indirizzo 192.168.1.3. Possono anche essere usate le parole chiave ‘ALL’, per designare qualsiasi elaboratore, e ‘EXCEPT’ per indicare un’eccezione a una regola (ad esempio ‘host allow 192.168.1. EXCEPT 192.168.1.3’). Si deve inoltre notare che in caso di assenza delle direttive ‘host allow’ e ‘host deny’, l’accesso è concesso a tutti in modo predefinito. Infine si tenga presente che tali direttive possono essere inserite anche in specifiche condivisioni ma con grado di priorità inferiore rispetto a quanto specificato nella sezione ‘global’. La direttiva ‘interfaces’ è utile in caso il servente Samba risieda in più di una sottorete. Se sull’elaboratore sono presenti più interfacce di rete, in modo predefinito, Samba si mette in ascolto di richieste provenienti dagli indirizzi di rete corrispondenti alla rete della prima interfaccia che trova (di solito eth0). Per fare in modo che invece risponda alle richieste provenienti da più sottoreti si deve impostare questa opzione. Nell’esempio Samba si pone in ascolto dalle sottoreti ‘192.168.1.*’ e ‘172.16.*.*’ (si può usare anche una notazione con maschera di rete: ‘192.168.1.1/255.255.255.0’ ‘172.16.244.1/255.255.0.0’). Ponendo ‘bind interfaces only = yes’ (l’alternativa è ovviamente ‘no’ oppure si può evitare di inserire questa opzione), si forza il servente a rispondere soltanto alle sottoreti corrispondenti alle interfacce indicate in ‘interfaces’. In tal caso si deve inserire tra le interfacce anche 127.0.0.1 per permettere al programma ‘smbpasswd’ di potersi collegare al localhost e funzionare correttamente. # # opzioni per la stampa # printing = bsd printcap name = /etc/printcap load printers = yes La direttiva ‘printing’ permette di specificare il sistema di stampa in uso nel servente; per i sistemi GNU/Linux il valore da indicare è di solito ‘bsd’, l’alternativa più diffusa è ‘sysv’. Le altre due opzioni permettono di caricare automaticamente tutte le stampanti configurate nel sistema senza descriverle singolarmente, indicando a tale scopo il percorso del file ‘printcap’ contenente la definizione di tali stampanti. La loro configurazione relativamente a Samba viene poi indicata nell’apposita sezione ‘printers’ descritta più avanti. # # opzioni per il log # log file = /var/log/samba/%m.log max log size = 100 log level = 3 La direttiva ‘log file’ permette di indicare il file delle registrazioni per gli eventi Samba; tale file può essere unico oppure, come nell’esempio, diverso per ogni cliente che si collega al servente (il nome del file sarà ‘nome_host .log’). Altra possibilità è quella di avere un file di registrazioni per ogni utente usando opportunamente la variabile ‘%U’ o ‘%u’. Con ‘max log size’ si specifica la grandezza in kibibyte del file delle registrazioni, raggiunta la quale il file stesso viene rinominato con estensione ‘.old’ e reinizializzato; il file ‘.old’ eventualmente già esistente viene cancellato. Il valore predefinito di questo parametro è 5000; il valore zero significa nessun limite di ampiezza (scelta non consigliabile per evitare una crescita abnorme del file o dei file delle registrazioni). La direttiva ‘log level’ indica il livello di dettaglio dei messaggi annotati nel registro; il valore predefinito è zero e corrisponde a nessun messaggio. Aumentando questo valore si hanno messaggi sempre più dettagliati; è comunque sconsigliabile un livello superiore a 3. 2252 Servente Samba # # opzioni per l’accesso alle condivisioni # encrypt password = yes null password = yes guest account = utentesmb security = share # in alternativa ; security = user ; security = server ; security = domain # altri parametri nel caso di security = user ; smb passwd file = /etc/samba/smbpasswd ; username map = /etc/samba/smbusers # altri parametri nel caso di security = server o domain ; password server = SERVER_NT La direttiva ‘encrypt password = yes’ è praticamente obbligatoria se il servente Samba deve «convivere» con macchine equipaggiate con sistemi operativi MS-Windows 98/NT o più recenti che usano le parole d’ordine cifrate. La direttiva ‘null password = yes’ permette di avere utenti Samba con parola d’ordine nulla (il valore predefinito è ‘no’.) La direttiva ‘guest account’ indica il nome di un utente generico al quale può essere consentito l’accesso alle condivisioni (da usare nel caso di ‘security = share’, come dettagliato più avanti). Tale utente deve essere definito nel sistema GNU/Linux senza directory personale e senza shell, aggiungendo al file ‘/etc/passwd’ la riga: utentesmb::499:499:utente generico samba:/dev/null:/dev/null. Il valore predefinito è ‘nobody’. Il parametro ‘security’ è di importanza fondamentale e richiede una trattazione leggermente più ampia. 207.3.1.1 Livello di sicurezza «share» Con l’impostazione ‘security = share’ si ha il controllo di accesso a livello di condivisione: il cliente che vuole accedere a una risorsa invia ogni volta una parola d’ordine e nessun nominativo-utente. Samba tenta di dedurre il nominativo-utente dalla direttiva ‘valid users’ eventualmente inserita nella sezione di condivisione di quella risorsa (come illustrato in seguito), oppure dal nome dell’elaboratore cliente, o, in caso di insuccesso, da quanto indicato con il parametro ‘guest account’ (questo solo se fra i parametri di condivisione è indicato ‘guest ok = yes’ e ‘guest only = yes’). Questo livello di sicurezza si usa, soprattutto nel caso di utenti MS-Windows e GNU/Linux non coincidenti, per condividere porzioni di file system quando si ha interesse a far sì che tutti gli utenti abbiano gli stessi diritti sui file condivisi (con l’impostazione ‘guest account = utentesmb’ il «proprietario» delle risorse condivise sarà sempre l’utente GNU/Linux ‘utentesmb’ qualunque sia il nominativo dell’utente MS-Windows che si connette). Servente Samba 2253 207.3.1.2 Livello di sicurezza «user» Con l’impostazione ‘security = user’, che è quella predefinita, si ha il controllo di accesso a livello di utente: il cliente che vuole accedere a una risorsa invia al momento della connessione una coppia utente-parola d’ordine in base alla quale avviene l’autenticazione da parte del servente. Se la connessione viene accettata il cliente può accedere a tutte le risorse condivise senza doversi autenticare nuovamente a ogni accesso. Il controllo delle utenze viene effettuato dal servente Samba in base al contenuto del file dei suoi utenti che solitamente è ‘/etc/samba/smbpasswd’ (si può cambiare il nome del file o il percorso tramite il parametro ‘smb passwd file =’). Gli utenti Samba vengono aggiunti con il comando ‘smbpasswd’ illustrato in un paragrafo successivo. È di fondamentale importanza notare che comunque il nome utente Samba deve coincidere con il nome di un utente definito nel sistema GNU/Linux, in quanto quest’ultimo deve essere sempre in grado di assegnare un proprietario «valido» agli eventuali file creati o copiati dall’utente conneso all’interno della risorsa condivisa. Questa esigenza può costituire un problema, ad esempio per la limitazione a otto caratteri dei nominativi-utente di GNU/Linux, che viene in parte superato grazie all’uso di un file di corrispondenza tra utenti GNU/Linux e utenti MS-Windows, il cui nome è indicato con la direttiva ‘username map =’. Un valore abbastanza comune di tale parametro è ‘/etc/samba/ smbusers’. Tale file conterrà delle righe così formate: nome_linux = nome_smb_1 nome_smb_2 ... Per ovvi motivi di sicurezza, entrambi i file ‘smbusers’ e ‘smbpasswd’, devono essere accessibili sia in scrittura che in lettura dal solo utente ‘root’. 207.3.1.3 Livello di sicurezza «server» Con l’impostazione ‘security = server’ si ha lo stesso controllo di accesso visto nel caso di ‘user’ con la differenza che l’utenza viene controllata su un servente esterno (solitamente un PDC MS-Windows) il cui nome (NetBIOS) viene indicato con la direttiva ‘password server =’. 207.3.1.4 Livello di sicurezza «domain» Con l’impostazione ‘security = domain’ si ha ancora lo stesso controllo di accesso visto nel caso di ‘user’, ma questa volta il servente Samba va a inserirsi in un dominio MS-Windows NT/2000. Per ottenere questo risultato occorre fermare i demoni di Samba, quindi aggiungere il servente Samba al dominio NT sul PDC usando il server manager di MS-Windows NT oppure a una active directory sul servente MS-Windows 2000 con la MMC (Microsoft management console) attraverso lo strumento «Utenti e computer di Active Directory». A questo punto si deve eseguire il comando: smbpasswd -j nome_dominio -r nome_server -Unome_utente %parola_d’ordine Il nome_dominio deve essere lo stesso indicato nella direttiva ‘workgroup’ di ‘smb.conf’; il nome_server deve coincidere con il valore di ‘password server’; nome_utente e relativa parola_d’ordine devono rappresentare un’utenza con privilegi sufficienti ad aggiungere un’utenza nuova nella macchina MS-Windows NT/2000. 2254 Servente Samba Ultimate queste operazioni occorre naturalmente riavviare il servizio Samba. Il vantaggio principale dell’impostazione ‘domain’ rispetto a quella ‘server’ consiste nel fatto che il PDC risulta meno carico, in quanto non è più necessaria una connessione di rete permanente tra esso e il servente Samba. Quest’ultimo infatti effettua una chiamata RPC (Remote procedure call) solo al momento dell’autenticazione e non necessita di essere costantemente connesso al PDC come avviene nel caso del livello di sicurezza ‘server’. Per concludere occorre notare che comunque anche con questo tipo di impostazione (come pure per quella ‘server’) è necessario tenere allineati gli elenchi degli utenti dal lato MS-Windows e dal lato GNU/Linux (il motivo è stato illustrato nel paragrafo del livello ‘user’). Ci sono però due direttive della sezione ‘global’ che permettono di automatizzare l’aggiornamento degli utenti GNU/Linux: add user = script_1 %u delete user = script_2 %u La prima entra in azione quando, a seguito di una connessione di un cliente MS-Windows, Samba si rivolge al servente di dominio per l’autenticazione con esito positivo ma l’utente GNU/Linux corrispondente non esiste; ovviamente lo script script_1 deve essere scritto in modo adeguato affinché crei l’utente ricevendolo come parametro dalla variabile ‘%u’. In modo speculare si usa l’altra direttiva che entra in azione quando, a seguito di una connessione di un cliente MS-Windows, Samba si rivolge al servente di dominio per l’autenticazione con esito negativo ma il corrispondente utente GNU/Linux esiste; in questo caso script_2 deve provvedere a cancellare l’utente in questione. 207.3.2 smb.conf: sezioni generiche di condivisione Una sezione indicante una risorsa condivisa può avere un nome a piacere purché sempre racchiuso tra parentesi quadrate. Vengono adesso illustrati alcuni esempi allo scopo di descrivere almeno le direttive più importanti: # # condivisione 1: una directory accessibile solo a certi utenti # [Pagine WWW] comment = Dir per le pagine web browseable = yes public = no path = /var/www writable = yes valid users = utente1 utente2 La direttiva ‘comment’ serve ad associare una descrizione alla risorsa condivisa. L’opzione ‘browseable’ permette di rendere visibile o no la risorsa agli utenti che si connettono al servente. ‘public’ è un sinonimo di ‘guest ok’; in questo esempio non si vuole che la risorsa sia accessibile per l’utente generico. ‘path’ permette di indicare il percorso della risorsa sul sistema GNU/Linux. ‘writable’ serve a concedere o negare l’accesso in scrittura (un sinonimo è ‘writeable’. ‘valid users’ indica quali sono gli utenti che possono accedere alla risorsa. È anche possibile indicare gruppi di utenti GNU/Linux con la sintassi ‘+nome_gruppo ’ e gruppi di utenti NIS (ov- Servente Samba 2255 viamente deve essere presente in rete un servente NIS) con la sintassi ‘&nome_gruppo ’ e anche entrambi con la sintassi ‘+&nome_gruppo ’ o ‘&+nome_gruppo ’, o ancora ‘@nome_gruppo ’. # # condivisione 2: una directory pubblica = accessibile a tutti # [public] comment = Dir pubblica browseable = yes guest ok = yes path = /usr/local/public writable = yes # # condivisione 3: una directory pubblica = accessibile a tutti in cui tutti # gli utenti possano creare, modificare, cancellare tutti i file # [temp] comment = Dir pubblica plus browseable = yes guest ok = yes guest only = yes path = /tmp writable = yes La differenza tra le due condivisioni è molto sottile ma anche interessante. La presenza di ‘guest ok = yes’ permette le connessioni anonime; eventuali file creati o copiati nella directory sarebbero di proprietà dell’utente indicato in ‘guest account’ in caso di accesso anonimo, oppure dell’utente effettivo in caso esso fosse registrato in GNU/Linux. Se è presente anche ‘guest only = yes’ invece il proprietario è sempre l’utente fittizio ‘ospite’ anche nel caso l’utente collegato fosse riconosciuto regolarmente da GNU/Linux; in questo caso quindi tutti gli utenti possono fare tutte le operazioni con qualsiasi file presente nella directory condivisa. Un modo alternativo per ottenere lo stesso risultato è quello di usare la direttiva ‘force user = nome_utente ’; in questo modo Samba assegna lo stesso nominativo-utente a chiunque si connetta alla risorsa. # # condivisione 4: un cd-rom # [cd] comment = CD-ROM preexec = mount /mnt/cdrom postexec = umount /mnt/cdrom browseable = yes public = yes path = /mnt/cdrom writable = no Il significato delle impostazioni è ovvio compreso quello delle due opzioni ‘preexec’ e ‘postexec’. In caso si tema che possano connettersi utenti sprovvisti dei privilegi per montare e smontare il CD, si possono sostituire le due direttive rispettivamente con ‘root preexec’ e ‘root postexec’ che svolgono lo stesso compito ma con i privilegi dell’utente ‘root’. 2256 Servente Samba # # condivisione 5: una directory privata con permessi preimpostati # [privata] comment = Dir privata browseable = yes path = /usr/local/private writable = no public = no write list = pippo pluto create mask = 0644 directory mask = 0644 In questo esempio nella directory non sarebbe possibile scrivere, ma la presenza della direttiva ‘write list’ permette di impostare permessi di scrittura, per gli utenti indicati, indipendentemente da quanto specificato negli altri parametri. Si deve però notare che i permessi impostati a livello di sistema su quella risorsa hanno sempre il sopravvento su quanto specificato nel file di configurazione di Samba (in altre parole, se ‘/usr/local/private’ è di proprietà dell’utente ‘root’ e i permessi sono impostati a 6008, gli altri utenti non possono né leggere né scrivere alcunché in quella directory condivisa). Le ultime due direttive, infine, servono a indicare i permessi con cui verranno creati file e directory all’interno della risorsa condivisa; il valore predefinito è 07558 Altre direttive importanti sono: admin users = tizio follow symlinks = no Con la prima si indica che l’utente ‘tizio’ ha gli stessi privilegi dell’utente ‘root’ sulla condivisione e quindi non risente di eventuali limitazioni dovute ai permessi sui file; con la seconda si impedisce che vengano seguiti i collegamenti simbolici evitando che chi accede alla condivisione possa accedere anche a file che si trovano all’esterno di questa. 207.3.3 smb.conf: sezione «homes» La sezione ‘homes’ viene utilizzata affinché ogni utente possa avere accesso a una propria directory personale sul servente Samba che potrà anche coincidere con la directory personale GNU/Linux di quell’utente. Un esempio di definizione può essere il seguente: # # directory personali degli utenti # [homes] comment = directory home browseable = no writable = yes path = usr/local/samba/%S Qui è importante l’impostazione che impedisce la scansione della risorsa in modo che essa non appaia con il nome ‘homes’ a tutti gli utenti. La presenza di ‘path’ serve a fare in modo che questa directory non coincida con quella GNU/Linux dell’utente (cosa che sarebbe l’impostazione predefinita). La logica di funzionamento è la seguente: quando l’utente si connette, se l’utenza è accettata, viene creata dal servente Samba una condivisione con le caratteristiche specificate nella sezione ‘homes’ ma con un nome uguale a quello dell’utente connesso. Servente Samba 2257 207.3.4 smb.conf: sezione «printers» Con questa sezione si impostano i parametri di configurazione di tutte le stampanti definite nel sistema GNU/Linux a patto che nella sezione ‘global’ siano state inserite le direttive seguenti: load printers = yes printcap name = /etc/printcap L’alternativa, che consiste nel definire le varie stampanti come singole risorse condivise, non viene presa in esame in questa sede. Un esempio di configurazione per le stampanti è il seguente: # # Stampanti # [printers] comment = stampanti path = /var/spool/samba browseable = no printable = yes public = yes writable = no Qui occorre notare che il parametro ‘path’ serve a impostare una directory per la coda di stampa, diversa da ‘/tmp/’ che è quella predefinita. Altra direttiva da segnalare è ‘printable’ con la quale si attiva la coda di stampa. 207.4 Programmi ausiliari per un servente Samba Un primo strumento molto utile è ‘testparm’ con il quale si verifica la correttezza sintattica delle impostazioni scritte nel file ‘smb.conf’. Il comando da eseguire è: # testparm /etc/samba/smb.conf si ottiene una risposta suddivisa in due parti: prima il resoconto del controllo sintattico del file di configurazione, poi l’elenco delle risorse condivise descritte in esso. Altro programma di fondamentale importanza è ‘smbpasswd’, già visto in precedenza a proposito della connessione di Samba a un dominio MS-Windows NT, ma che si usa principalmente per definire utenti e parole d’ordine relative. La sintassi in questo caso è: smbpasswd [-a] [-x] [nominativo ] L’opzione ‘-a’ permette di inserire un nuovo utente e poi di definirne la parole d’ordine; l’opzione ‘-x’ permette invece di eliminarlo; se non si indica alcuna opzione si esegue solo il cambio della parole d’ordine per l’utente. Il nominativo-utente che si può inserire alla fine della riga di comando è quello sul quale il comando opera (se non viene indicato, si fa riferimento in modo predefinito all’utente GNU/Linux che esegue il comando). Altro strumento utile è lo script ‘smbadduser’ che permette di definire un nuovo utente Samba e contemporaneamente l’associazione con utenti GNU/Linux corrispondenti. La sintassi è: smbadduser utente_linux :utente_smb [utente_linux :utente_smb ]... In pratica questo comando aggiorna i file ‘smbpasswd’ e ‘smbusers’, permettendo di definire la parola d’ordine per i nuovi utenti Samba. 2258 Servente Samba Infine può essere molto utile anche il comando ‘smbstatus’ per avere un rapporto (con l’opzione ‘-d’ anche dettagliato) delle connessioni Samba attive. Maggiori dettagli sulla configurazione di un servente Samba si possono trovare anche nella documentazione fornita insieme al pacchetto in ‘/usr/share/doc/samba-x.y.z ’, oppure consultando la pagina di manuale smb(5). Capitolo 208 Samba dal lato cliente Da una macchina GNU/Linux è possibile connettersi a un servente Samba o a macchine MSWindows per accedere alle risorse che queste condividono grazie a una serie di strumenti che costituiscono il «lato cliente» di Samba. 208.1 smbclient Il primo programma da esaminare è ‘smbclient’ che si usa fondamentalmente in due maniere: smbclient -L nome_server_samba per avere la lista delle risorse condivise dal servente; oppure: smbclient nome_servizio [-U nominativo_utente ] per connettersi alla risorsa nome_servizio (ad esempio ‘//serversamba/public’). Se la connessione ha successo si ha a disposizione un’interfaccia testuale del tutto simile a quella del programma ‘ftp’ tradizionale, dove si possono eseguire più o meno gli stessi comandi (‘get’, ‘put’, ‘cd’, ‘pwd’, ecc.). Un’opzione importante è ‘-I’ seguita da un numero IP, con la quale si può appunto indicare il numero IP del servente a cui ci si vuole connettere. 208.2 smbmount Sicuramente l’interfaccia messa a disposizione da ‘smbclient’ non è il massimo della comodità; sarebbe molto meglio poter disporre della risorsa condivisa da un’altra macchina come se fosse una risorsa locale. Anche questo si può ottenere con Samba, in particolare grazie a ‘smbmount’. La sintassi è: smbmount nome_servizio punto_di_innesto [-o ] opzioni Ad esempio: # smbmount //serversamba/public /mnt/dirsamba -o username=tizio%parola_d’ordine Per smontare la risorsa si può usare il comando: smbumount punto_di_innesto È anche possibile ottenere l’inserimento automatico della risorsa all’avvio di GNU/Linux con la riga seguente nel file ‘/etc/fstab’: //serversamba/public /mnt/dirsamba smbfs username=tizio%parola_d’ordine È importante ribadire che in questa sede non viene illustrata la sintassi completa dei vari comandi con l’elenco di tutte le opzioni possibili. Per avere queste informazioni si deve consultare la documentazione dei vari pacchetti e il manuale in linea (per esempio smbpasswd(8)). 2259 2260 Samba dal lato cliente 208.3 Uso con Samba di stampanti MS-Windows Per usare su una macchina GNU/Linux una stampante condivisa da una macchina MS-Windows, occorre impostare in modo opportuno il file di definizione delle stampanti GNU/Linux: ‘/etc/ printcap’. Ecco un esempio di righe di configurazione da aggiungere a tale scopo: stsamba:\ :mx=0:\ :sh:\ :sd=/var/spool/lpd/stsamba:\ :lp=/dev/null:\ :af=/var/spool/lpd/stsamba/acct:\ :if=/usr/bin/smbprint: Una breve spiegazione sul significato di queste righe è necessaria, anche se lo studio del file di configurazione delle stampanti in GNU/Linux esula dallo scopo di questo documento: ‘mx=0’ indica nessun limite di grandezza dei file da stampare; ‘sd=’ indica la directory della coda per questa stampante; ‘lp=/dev/null’ indica che la stampante non è collegata ad alcuna porta (non è locale); ‘af=’ indica il nome del file per registrare le transazioni; ‘if=’ indica il nome del filtro da usare per la stampa; quello usato nell’esempio è un filtro fornito in modo predefinito con la distribuzione Red Hat all’interno del pacchetto ‘samba-client’. Affinché il tutto funzioni è poi necessaria la presenza del file ‘.config’ nella directory della coda indicata con la riga ‘sd=’. Un esempio del suo contenuto è il seguente: share="//server_smb /nome_stampante_condivisa " user="tizio" password="blablabla" Data la complessità della configurazione manuale di una stampante SMB in GNU/Linux (e anche di una stampante in generale), può essere consigliabile l’uso di strumenti appositi come ‘printconf-gui’ che semplificano molto queste operazioni. 208.4 Altri strumenti utili Altri comandi presenti nel pacchetto ‘samba-client’ sono: ‘nmblookup’ che permette di trovare il numero IP di una macchina fornendo il nome NetBIOS; ‘findsmb’ che fornisce informazioni sui serventi Samba presenti in rete; ‘smbtar’ che permette di effettuare copie di sicurezza di risorse SMB su unità a nastro installate sul servente GNU/Linux. Per i dettagli di uso di questi comandi si rimanda ai rispettivi manuali in linea. Capitolo 209 Samba come servente WINS In una rete basata su NetBIOS la risoluzione dei nomi è basata sull’invio di messaggi circolari; quando un elaboratore con MS-Windows si collega in rete invia un messaggio a tutti informando sul proprio nome e sul proprio indirizzo. È ovvio che un sistema di questo tipo può essere efficiente solo su piccole reti e in assenza di sottoreti multiple (i router di solito sono configurati per bloccare i messaggi circolari). La soluzione a questo problema proposta da Microsoft consiste nell’introduzione di un servente WINS allo scopo di gestire una tabella contenente le associazioni tra nomi NetBIOS e indirizzi IP. I clienti della rete hanno impostata l’indicazione del numero IP del servente WINS in modo che, quando devono qualificarsi o chiedere informazioni circa l’identità di altre macchine, si rivolgono direttamente al servente senza generare traffico superfluo. Un servente Samba può essere configurato sia per svolgere la funzione di servente WINS sia per essere cliente di un servente WINS già presente in rete (ovviamente non sono possibili entrambe le impostazioni contemporaneamente). Nella sezione ‘global’ si deve aggiungere il seguente parametro per attivare il servente WINS: wins support = yes Invece per indicare a Samba qual è il servente WINS già attivo in rete si usa: wins server = 192.168.1.1 2261 Capitolo 210 Samba e la scansione della rete In una rete locale le macchine hanno sempre una lista delle altre macchine attive che si chiama lista di browse. Il servente che la gestisce si chiama master browser locale se riveste questo ruolo solo per una sottorete, se invece mantiene la lista per tutta la rete locale diviene un master browser di dominio. Siccome in una rete le macchine possono essere collegate e scollegate in ogni momento, il master browser locale aggiorna continuamente la lista e la invia alle macchine che ne fanno richiesta. Il master browser di dominio invece raccoglie le liste di ogni sottorete e le mette a disposizione dei master browser locali. Un elaboratore diventa master browser locale a seguito di una «elezione» che può essere effettuata in qualunque momento (ad esempio quando un nuovo elaboratore si presenta in rete). Riguardo a tale elezione Microsoft assegna ai suoi sistemi operativi un valore, detto livello, che cresce sempre di più per i sistemi operativi più recenti (ad esempio una macchina con MS-Windows 98 ha livello 2, una con MS-Windows NT 4 Workstation ha livello 17, una con MS-Windows NT 4-Server ha livello 32, una con MS-Windows 2000-Server ha livello 64). L’elezione avviene sulla base di questo valore; in caso di parità viene esaminata la funzione svolta dalla macchina (senza entrare in dettagli eccessivi, basti sapere che un PDC diviene sempre anche PDM); in caso di ulteriore parità viene scelta la macchina che è da più tempo in rete. Con Samba il livello per la partecipazione all’elezione può essere scelto in sede di configurazione. Nell’esempio seguente vengono mostrate le direttive da inserire nella sezione ‘global’ affinché il servente Samba sia master browser locale prevalendo su macchine MS-Windows equipaggiate fino a NT-server: local master = yes os level = 34 preferred master = yes La terza direttiva serve ad attivare il preferred master bit del servente Samba, in modo che il proprio servente prevalga al momento dell’elezione su macchine con uno stesso sistema operativo. Se si vuole che il servente Samba divenga master browser di dominio occorre inserire anche: domain master = yes In caso però che il servente partecipi a un dominio NT è preferibile che il ruolo di master browser di dominio sia lasciato al PDC (che comunque, come viene descritto nel prossimo capitolo, può essere lo stesso servente Samba). A proposito della scansione della rete, nel caso siano presenti sottoreti multiple, è opportuno ricordare le seguenti regole generali: • ci deve essere una macchina MS-Windows o Samba che faccia da master browser locale per ciascuna sottorete (se nella sottorete c’è gia un master browser di dominio non è necessario anche il master browser locale); • almeno una macchina MS-Windows o Samba deve essere master browser di dominio per il gruppo di lavoro; • ogni master browser locale deve sincronizzarsi con il master browser di dominio. In caso nella rete non sia presente un master browser di dominio e ci siano però delle sottoreti multiple, Samba mette a disposizione due direttive utili per la sincronizzazione (da inserire sempre nella sezione ‘global’): 2262 Samba e la scansione della rete 2263 remote announce = 192.168.1.255/INF 192.168.2.255/INF remote browse sync = 192.168.3.255 192.168.4.255 Con ‘remote announce’ il servente Samba fornisce l’elenco di scansione anche ad altre sottoreti. Se si conoscono i numeri IP dei master browser locali si possono indicare tali numeri, altrimenti (come nell’esempio) si indicano degli indirizzi broadcast. In pratica con i valori indicati, il servente Samba segnalerà la sua presenza a tutte le macchine delle sottoreti 192.168.1. e 192.168.2. (del gruppo di lavoro INF) e quindi anche ai relativi master browser locali. * * L’altra direttiva ha uno scopo simile nel caso però i master browser locali delle sottoreti siano altri serventi Samba (anche in questo caso si possono indicare gli indirizzi precisi dei servente o degli indirizzi broadcast). Nell’esempio, un servente Samba contatta altri serventi Samba delle sottoreti 192.168.3. e 192.168.4. , con i quali sincronizza le liste di scansione. * * A proposito della possibilità di usare gli indirizzi broadcast ci si deve sincerare che i router della rete non siano configurati per bloccare il traffico broadcast tra sottoreti diverse. Capitolo 211 Autenticazione di utenti MS-Windows con Samba A partire dalla versione 2.0 è possibile configurare Samba come domain controller e autenticare gli utenti degli elaboratori clienti MS-Windows 95/98 sostituendo un servente MS-Windows NT/2000. Con la versione 2.1 è stata data la possibilità di accreditare anche clienti MS-Windows NT. Dalla versione 2.2, che è la più recente, Samba può accreditare anche clienti MS-Windows 2000/XP, partecipare a una ADS (Active directory service) ed è stato aggiunto il demone ‘winbind’ che consente di usare un domain controller MS-Windows come servente per le utenze, allineando del tutto le utenze di GNU/Linux con quelle di MS-Windows e centralizzando la loro gestione su un solo sistema. È sicuramente anche il caso di elencare ciò che Samba non può fare (almeno per il momento): • utilizzo di BDC (Backup domain controller) in domini NT e Active directory replication con MS-Windows 2000; • partecipazione ad alcun tipo di trust relationship; • sostituzione di un MS-Windows 2000-Server. In questa sede viene presa in esame solo la configurazione di Samba come PDC per l’accreditamento di clienti MS-Windows 95/98/Me/NT. Di seguito viene presentato un possibile file ‘smb.conf’ con le definizioni necessarie affinché Samba sia un PDC: [global] netbios name = ServerSamba workgroup = INF server string = Samba Server NT log file = /var/log/samba/%m.log max log file = 50 security = user encrypt password = yes smb password file = /etc/samba/smbpasswd local master = yes preferred master = yes os level = 33 domain master = yes ; domain logons = yes ; # script di accesso fisso per tutti logon script = logon.bat # oppure uno per ogni cliente ; logon script = %m.bat # oppure uno per ogni utente ; logon script = %U.bat ; # profili utenti logon path = \\ServerSamba\profile\%U [netlogon] comment = Directory degli script di inizializzazione 2264 Autenticazione di utenti MS-Windows con Samba 2265 path = /home/netlogon read only = yes guest ok = yes browseable = no [home] comment = Dir utente path = /home/%U browseable = yes writable = yes [public] comment = Dir pubblica path = /home/public browseable = yes writable = yes public = yes create mask = 0777 211.1 Domain logons È la direttiva che permette di configurare Samba come PDC in quanto lo imposta come servente di autenticazione di dominio. 211.2 Logon script Samba consente l’esecuzione degli script di accesso di MS-Windows (‘.BAT’ o ‘.CMD’). Tali script vengono eseguiti sul cliente al momento della connessione di un utente al dominio ma sono memorizzati sul servente e vengono quindi trasferiti attraverso la rete. Ovviamente sono molto utili per impostare dinamicamente le configurazioni di rete per gli utenti quando si connettono. L’opzione ‘logon script’ permette appunto di indicare il nome dello script da eseguire quando l’utente si collega; come si vede dall’esempio può essere uno script unico, valido per tutti, oppure dipendente dal cliente o dal nome utente. Sul servente GNU/Linux questi script vengono memorizzati nella directory indicata nella condivisione ‘netlogon’, che viene descritta più avanti. Una cosa importante da ricordare è che gli script di accesso vengono eseguiti in ambiente MSWindows e devono essere quindi scritti con righe terminanti con i caratteri di <CR> e <LF>, invece del solo <LF> di un sistema GNU/Linux. L’esempio seguente di script di accesso, definisce un disco di rete ‘W:’ su una condivisione di Samba: echo Connette disco di rete net use w: \\ServerSamba\dati 211.3 Logon path In MS-Windows 95/98 ciascun utente può avere il proprio profilo comprendente informazioni sull’aspetto della scrivania grafica, sulle applicazioni che appaiono nel menù Start, sullo sfondo e altre ancora. Tale profilo può essere memorizzato direttamente su un elaboratore cliente e si chiama allora «profilo locale», oppure sul servente e si chiama «profilo di roaming», in quanto l’utente ha a disposizione sempre lo stesso ambiente anche spostandosi da un cliente all’altro. La direttiva ‘logon path’ viene usata per indicare dove vengono memorizzati i profili dei vari utenti. 2266 Autenticazione di utenti MS-Windows con Samba 211.4 Logon home e logon drive Con ‘logon home’ si indica la posizione della directory personale di un utente, che può essere diversa da quella indicata nella sezione ‘homes’. Con ‘logon drive’, da usare solo in caso di clienti MS-Windows NT, si indica la lettera del disco su un client in cui vengono abbinate le directory personali indicate con ‘logon home’. 211.5 Sezione [netlogon] In questa sezione viene configurata una condivisione speciale che serve a contenere gli script di accesso. La configurazione scelta nell’esempio (sola lettura, pubblica, non visibile alla scansione delle risorse) è dettata dal ruolo particolare che svolge. 211.6 Definizione delle utenze per macchina Nel caso nella rete siano presenti dei clienti MS-Windows NT, per essi devono essere creati sul PDC i cosiddetti machine account in aggiunta alle utenze normali. Ovviamente, tali utenze speciali devono essere inserite sia come utenti Samba che come utenti del sistema GNU/Linux che ospita il servente. Tale operazione può essere fatta in modo automatico (direttiva ‘add user’ illustrata in precedenza) oppure manualmente, con i seguenti comandi: /usr/sbin/useradd -d /dev/null -g 100 -c"descrizione_dell’elaboratore_client " ←,→-s /bin/false nome_elaboratore $ passwd -l nome_elaboratore $ smbpasswd -a -m nome_elaboratore È necessario prestare attenzione al carattere ‘$’ alla fine del nome della macchina nel primo e nel secondo comando. Il secondo comando permette di bloccare la parola d’ordine di quell’utente fittizio. Con il terzo comando si definisce l’utente ‘nome_elaboratore ’ per Samba grazie all’opzione ‘-m’. Capitolo 212 Accesso a GNU/Linux da parte di utenti di un dominio MS-Windows con Winbind In precedenza, nel capitolo sull’impostazione di un servente Samba, è stato illustrato come integrare quest’ultimo in un dominio MS-Windows NT o in una active directory di MS-Windows 2000. In particolare si è visto come questo sia possibile impostando il livello di sicurezza al valore ‘domain’ ed eseguendo un opportuno comando ‘smbpasswd’. Grazie a Winbind, un nuovo strumento di Samba presente dalla versione 2.2.2, diventa addirittura possibile l’autenticazione degli utenti GNU/Linux (attenzione: utenti GNU/Linux, non utenti Samba) presso il domain controller windows. Ciò può essere molto utile in quei contesti in cui si vogliano inserire elaboratori con GNU/Linux in reti già consolidate su piattaforma MS-Windows, utilizzando le informazioni su utenti e gruppi preesistenti senza essere costretti a ridefinirle anche per le macchine GNU/Linux. Winbind è costituito da un piccolo gruppo di componenti disponibili all’interno del pacchetto ‘samba-common’; in dettaglio ne fanno parte: • una libreria per il NSSwitch (Name service switch); • una libreria per i moduli PAM (Pluggable authentication modules); • un programma di servizio, ‘wbinfo’, e un demone, ‘winbindd’. Il servizio NSSwitch è presente in tutte le moderne librerie C e permette di ottenere i dati relativi a utenti, gruppi e nodi, da varie fonti (ad esempio NIS, DNS, ecc.); Winbind diventa un’ulteriore fonte di informazioni per NSSwitch relativamente a utenti e gruppi di un dominio MS-Windows. Il PAM è un sistema generalizzato per la gestione dei metodi di autenticazione per molteplici servizi (quelli per cui esistono le librerie PAM relative); grazie all’apposita libreria PAM, Winbind fornisce anche il servizio di autenticazione. 212.1 Configurazioni necessarie 212.1.1 smb.conf Per configurare il servizio Winbind occorre intervenire innanzitutto nel file ‘smb.conf’ inserendo le direttive seguenti: workgroup name = nome_dominio_NT encrypt password = yes security = domain password server = nome_PDC_WIN ; impostazioni per il demone winbindd winbind separator = + template shell = /bin/bash template homedir = /home/%D/%U winbind uid = 10000-20000 winbind gid = 10000-20000 winbind enum users = yes winbind enum groups = yes Con ‘winbind separator’ si imposta il carattere usato per ottenere il nome utente GNU/Linux dall’unione di nome di dominio e nome utente NT; il valore predefinito corrisponde a ‘\’, ma è 2267 2268Accesso a GNU/Linux da parte di utenti di un dominio MS-Windows con Winbind sconsigliabile, in quanto ha un significato speciale nella shell di GNU/Linux; invece, la scelta del carattere ‘+’ dovrebbe essere quella migliore. Con ‘template shell’ si imposta la shell degli utenti. Con ‘template homedir’ si definisce la directory personale degli utenti; nell’esempio si usano le variabili ‘%D’ e ‘%U’ in modo che ogni utente abbia come directory ‘/home/nome_dominio_nt / nome_utente_nt ’. ‘winbind uid’ e ‘winbind gid’ permettono di impostare gli intervalli di numeri di identifica- zione per utenti e gruppi che Winbind utilizza per riabbinare gli utenti e i gruppi MS-Windows a utenti e gruppi GNU/Linux. ‘winbind enum users’ e ‘winbind enum groups’ permettono di attivare l’enumerazione di gruppi e utenti. 212.1.2 Modifiche ai file di configurazione dei moduli PAM Le modifiche ai file di configurazione dei moduli PAM devono essere effettuate con molta attenzione in quanto errori in questa fase possono causare anche l’impossibilità di accedere. Può quindi essere opportuno fare una copia dei file interessati alle modifiche in modo da poter ripristinare la situazione precedente in ogni momento. Maggiori informazioni sul funzionamento dei moduli PAM non possono essere fornite in questa sede; eventualmente si può consultare il capitolo 56. Nel file ‘/etc/pam.d/system-auth’ deve essere aggiunta la riga: auth sufficient /usr/lib/security/pam_winbind.so dopo la prima riga ‘auth’ già presente e trasformata la riga: auth sufficient /lib/security/pam_unix.so likeauth nullok in: auth sufficient /lib/security/pam_unix.so likeauth nullok use_first_pass Nel file ‘/etc/pam.d/login’ devono essere aggiunte le seguenti due righe, rispettivamente come prima riga ‘account’ e come ultima riga ‘session required:’ account sufficient /lib/security/pam_winbind.so ... session required /lib/security/pam_mkhomedir.so skel=/etc/skel/ umask=0022 L’ultima è molto importante in quanto permette la creazione automatica della directory personale dell’utente al primo accesso alla macchina GNU/Linux. Riguardo la modifica al file ‘system-auth’ occorre osservare che, essendo la sua configurazione usata, attraverso il modulo ‘pam_stack’, in molti altri file di configurazione dei moduli PAM (e non solo in ‘login’), sarebbe più opportuno lasciarlo invariato definendone uno nuovo con le modifiche e con nome leggermente diverso. Se si opta per questa scelta è ovvio che si devono modificare opportunamente i riferimenti al file ‘system-auth’ contenuti nel file ‘login’. Accesso a GNU/Linux da parte di utenti di un dominio MS-Windows con Winbind 2269 212.1.3 Modifiche alla configurazione di NSSwitch Nel file ‘/etc/nsswitch.conf’, contenente la configurazione del servizio NSSwitch, è necessario aggiungere Winbind tra le fonti dei dati relativi a utenti e gruppi. Ad esempio: passwd: group: files winbind files winbind L’ordine con cui vengono elencate le fonti è significativo e quindi è opportuno lasciare la priorità a ‘files’ in modo che per primi siano interrogati i file di sistema (‘/etc/passwd’ e ‘/etc/ group’). 212.2 Attivazione Per prima cosa occorre inserire la macchina GNU/Linux nel dominio MS-Windows operando come illustrato nel capitolo relativo alla configurazione di un servente Samba, nel paragrafo sul livello di sicurezza ‘domain’ (207.3.1.4). Occorre poi avviare i servizi ‘smb’ e ‘winbind’: # /etc/rc.d/init.d/smb start # /etc/rc.d/init.d/winbind start Si può verificare il buon funzionamento di Winbind con i comandi: # wbinfo -u # wbinfo -g con i quali si elencano rispettivamente utenti e gruppi del dominio MS-Windows. Si possono usare anche i comandi: # getent passwd # getent group per ottenere gli elenchi di tutti gli utenti e gruppi utilizzabili, sia quelli del dominio che quelli propri di GNU/Linux. Infine si può procedere all’accreditamento sulla macchina GNU/Linux di un utente del dominio MS-Windows ricordando che il nome utente è dato da ‘nome_dominio_nt +nome_utente_nt ’ e la parola d’ordine è ovviamente la stessa utilizzata in ambiente MS-Windows. Capitolo 213 Samba e DFS Il DFS (Distributed file system), introdotto con MS-Windows 2000, permette di organizzare le condivisioni di rete in una struttura ad albero svincolando gli utenti di tali risorse dalla conoscenza della reale collocazione delle stesse sui vari serventi. Con MS-Windows 95/98/NT è invece necessario, quando si deve connettere una risorsa, conoscere esattamente la sua collocazione in rete; si può ovviare in parte a questo inconveniente connettendo permanentemente la risorsa all’avvio dell’elaboratore cliente, ma in caso di spostamento della risorsa il problema si ripresenta. Con il DFS si vengono a creare dei «volumi di rete» che possono essere ispezionati come fossero residenti fisicamente su un solo servente. La struttura può poi essere duplicata, tutta o in parte, per ottenere maggiori garanzie contro le perdite di dati accidentali. Ogni struttura DFS ha una radice comune a tutte le condivisioni e numerose diramazioni (foglie), tutte di primo livello. Un servente può ospitare una sola radice mentre le foglie possono anche essere ospitate su macchine diverse. Sarebbe anche possibile ottenere strutture più complesse annidando radici di DFS come foglie di altri DFS ma qui non si considera tale possibilità. Samba può assumere il ruolo di servente DFS e ospitare una radice di un volume DFS grazie alla seguente direttiva nella sezione ‘global’: host msdfs = yes e alla definizione di questa nuova sezione: [dfs] path = /dir-expo/dfs msdfs root = yes Nella directory ‘/dir-expo/dfs’ del servente GNU/Linux si dovranno poi impostare i collegamenti simbolici agli altri serventi della rete procedendo come nell’esempio seguente: # cd /dir-expo/dfs # chown root /dir-expo/dfs # chmod 755 /dir-expo/dfs # ln -s msdfs:serverA\\shareA coll-a # ln -s msdfs:serverB\\shareBC,serverC\\shareBC coll-bc Il secondo collegamento dell’esempio associa a un solo nome di risorsa DFS, due condivisioni: queste saranno in fault tolerance tra di loro e l’allineamento dei dati al loro interno sarà assicurato dal servente DFS. Grazie alla definizione dei collegamenti simbolici, quando un cliente si collega a una risorsa DFS, viene ridiretto, in modo del tutto trasparente e automatico, verso la macchina che ospita fisicamente i dati condivisi. 2270 Parte xl Programmare in PHP Gianluca Giusti <brdp @ urcanet.it> 2002.11.05 2271 Gianluca Giusti si è diplomato in Informatica presso l’ITIS de L’Aquila, attualmente frequenta il corso di laurea in Fisica presso la Facoltà di Scienze MM.NN.FF. dell’Università de L’Aquila Lavora come analista programmatore nella città di Roma allo sviluppo di portali, siti di commercio elettronico, software di BI. È appassionato di amministrazione di sistema, in particolare GNU/Linux, e di reti informatiche. Programmare in PHP Copyright © 2001-2002 Gianluca Giusti brdp @ urcanet.it This information is free; 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 work 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 work; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Una copia della licenza GNU General Public License, versione 2, si trova nell’appendice A. 2272 non modificare ;) 2273 L’indirizzo della versione aggiornata dell’opera "Programmare in PHP" è: <http://www.urcanet.it/brdp/php_manual/> Al momento l’opera è incompleta, tuttavia ho ritenuto opportuno pubblicare quanto fatto. Scrivo questo documento nel tempo libero e ultimamente ne ho davvero poco quindi aggiornerò il contenuto ogni volta che un argomento sarà completato. Gli script di esempio sono contenuti e raggruppati per capitolo all’indirizzo <http://www.urcanet.it/ brdp/php_manual/esempi/> L’opera è inclusa in "Appunti di informatica libera" di Daniele Giacomini. La diffusione di questo documento è incoraggiata in base ai termini della licenza. 2274 Prefazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2277 214 Avere le idee chiare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2278 214.1 Cos’è il PHP? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2278 214.2 Cosa può fare il PHP? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2281 214.3 PHP su piattaforma Microsoft . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2281 214.4 Quanto costa il PHP? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2281 215 Le basi del linguaggio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2282 215.1 La sintassi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2282 215.2 Primo script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2284 215.3 Tipi di dati . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2285 215.3.1 215.3.2 215.3.3 215.3.4 215.3.5 215.3.6 integer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2286 boolean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2287 double . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2287 string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2288 array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2289 object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2293 215.4 Operatori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2293 215.4.1 215.4.2 215.4.3 215.4.4 215.4.5 215.4.6 Operatori aritmetici . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2293 Operatori di assegnazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2294 Operatori di controllo degli errori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2295 Operatori di incremento e decremento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2296 Operatori logici . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2297 Operatori di confronto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2297 215.5 Strutture di controllo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2297 215.5.1 if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2298 215.5.2 else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2299 215.5.3 elseif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2300 215.5.4 switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2302 215.5.5 while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2303 215.5.6 do..while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2305 215.5.7 for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2305 215.5.8 foreach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2306 215.5.9 break . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2308 215.5.10 include() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2309 216 Passaggio di variabili tramite l’HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2311 216.1 Metodo get . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2311 216.2 Metodo post . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2313 216.3 Quale metodo scegliere? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2313 216.4 Cosa è cambiato nel PHP versione 4.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2314 217 L’utilizzo delle funzioni in PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2315 2275 217.1 Le funzioni predefinite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2315 217.2 Le funzioni definite dall’utente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2317 217.3 Le funzioni ricorsive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2322 218 La gestione del file system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2324 218.1 Concetto di file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2324 218.2 Apertura di un file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2324 218.3 Lettura di un file di testo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2325 218.4 Scrittura in un file di testo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2327 218.5 Accodare testo in un file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2330 218.6 Conclusioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2332 Indice analitico del volume . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2333 2276 Prefazione Questo documento vuole essere una guida all’utilizzo di uno dei più versatili e potenti linguaggi di programmazione oggi diffuso in Internet. Il lettore non troverà un elenco delle funzioni del linguaggio, perché sarebbe inutile dal momento che queste notizie sono già disponibili nel manuale ufficiale; al contrario, potrà trovare una guida all’utilizzo degli strumenti che gli sviluppatori del linguaggio hanno messo a disposizione. Naturalmente ognuno potrà ampliare e personalizzare gli script proposti come esempio; sarà la guida stessa a sollevare dubbi e a suggerire delle modifiche, per il resto via libera all’immaginazione del lettore. Inutile dire che per qualsiasi problema la mia casella di posta è a vostra disposizione compatibilmente con gli impegni. Per la lettura della guida si darà per scontato: • la configurazione corretta della macchina che offre i servizi, in cui devono essere installati il servente HTTP (negli esempi di questa guida si fa riferimanto principalmente ad Apache), il modulo PHP 4 e una base di dati (DBMS), che negli esempi proposti è costituita da MySQL; • la conoscenza del linguaggio HTML; • un minimo di conoscenza del linguaggio SQL per l’interrogazione delle basi di dati di prova. Verranno risolti i problemi più comuni, progettati e realizzati i servizi necessari a un sito per essere moderno, dinamico e al passo coi tempi. Si pensi alla gestione di utenze, aree riservate, notizie, sondaggi, motori di ricerca, album fotografici, servizi FTP, ecc. Per fare questo si partirà da esempi molto semplici, scritti in modo altrettanto semplice, fino ad arrivare alla realizzazione di «classi» da utilizzare in tutti i nostri servizi. Prima di iniziare converrà collegarsi al sito <http://www.php.net> per scaricare il manuale ufficiale del PHP; sarà molto utile ed è importante saperlo consultare. Viene rilasciato in vari formati; probabilmente il più conveniente è il formato PDF. In tal modo, si disporrà di un unico file su cui poter effettuare ricerche di testo. Inoltre è importante ricordare che un gruppo di persone sta traducendo il manuale in italiano ospitato sul sito ufficiale all’indirizzo <http://www.php.net/ manual/it/>. Chi volesse partecipare può mettersi in contatto con i coordinatori del progetto Luca Perugini Simone Cortesi. 2277 Capitolo 214 Avere le idee chiare Prima di addentrarsi nella programmazione, è bene capire quali sono gli strumenti a disposizione e cosa permettono di fare. C’è molto interesse verso le tecnologie utilizzate in Internet, di conseguenza si crea spesso confusione. Una delle conseguenze più frequenti è ostinarsi a utilizzare un linguaggio nato con uno scopo per realizzare tutt’altro. 214.1 Cos’è il PHP? PHP sta per Hypertext Preprocessor. Dalla documentazione ufficiale il PHP viene definito come un «linguaggio script dal lato del servente immerso nel codice HTML». Di seguito la definizione nel dettaglio: «linguaggio script»: il PHP è un vero e proprio linguaggio di programmazione, è importante rendersi conto che l’HTML, ad esempio, non è un linguaggio di programmazione ma un linguaggio di descrizione e formattazione del testo. Inoltre, per i più esperti, il PHP è un linguaggio interpretato. «Dal lato del servente»: queste le parole fondamentali. Il codice PHP inserito tra i marcatori HTML viene interpretato dall’elaboratore servente e non dal navigatore del cliente. Il modo migliore per rendere l’idea è passare ad un esempio. Figura 214.1. Il servente elabora tramite l’interprete PHP gli script i quali generano le pagine HTML che vengono fornite al cliente tramite il protocollo HTTP. Si supponga di voler scrivere la data odierna in una pagina HTML. L’HTML non permette di farlo, in quanto, è un linguaggio di formattazione statico. Una soluzione potrebbe essere l’utilizzo di uno script Java di Netscape (JavaScript) ma è un linguaggio lato cliente. Il codice JavaScript viene eseguito dal navigatore del visitatore e non dal servente. Tutto ciò potrebbe portare alla visualizzazione di una data errata sulle pagine del sito solo perchè l’orario di sistema del visitatore non è impostato correttamente. Inoltre la guerra per il monopolio nel mercato dei navigatori 2278 Avere le idee chiare 2279 ipertestuali tra Microsoft e Netscape ha fatto sì che non ci sia uno standard, di conseguenza Netscape non gestiste molte istruzioni JScript di Microsoft e Explorer non riconosce molte istruzioni JavaScript di Netscape 1 . A questo punto l’ideale è fornire al navigatore una stringa HTML generata e formattata da una funzione PHP. Ecco come: 1 <html> 2 <head> 3 <title>La mia prima pagina php</title> 4 </head> 5 <body> 6 7 <br><br> 8 9 <?php echo date("d-m-Y") ?> 10 11 <br><br> 12 13 <a href="../cap_2/benvenuto.php">vai a benvenuto.php >></a> 14 15 </body> 16 </html> Una volta completato salvare il codice nel file ‘primo.php’. Se si prova ad aprire ‘primo.php’ dal menù file del navigatore il risultato è una pagina bianca. Il motivo sta nel fatto che il PHP è un «linguaggio dal lato del servente» dunque il navigatore (cliente) non è in grado di interpretarne il codice compreso tra i marcatori: ‘<?php ?>’ Per visualizzare la data in modo corretto è necessario dare il codice in pasto all’interprete PHP tramite il servente HTTP, quindi bisogna copiare il file ‘primo.php’ nella directory dei documenti del servizio HTTP e dal navigatore richiamare il file scrivendo l’indirizzo dell’elaboratore su cui è ospitato. Tutti gli script di esempio sono disponibili in rete all’indirizzo <http:// www.urcanet.it/brdp/php_manual/esempi/> e sono raccolti per capitolo. Se si scaricano gli script di esempio per essere eseguiti in locale e la configurazione del servente è corretta, il risultato sarà: Figura 214.2. Ecco come appare la pagina HTML <http://www.urcanet.it/brdp/php_manual/ esempi/cap_1/primo.php> sul navigatore del visitatore. Ben più interessante è osservare il sorgente della pagina <http://www.urcanet.it/brdp/php_manual/esempi/ cap_1/primo.php> dal menu visualizza del navigatore, ecco quello che viene inviato dal servente: 1 Netscape ha sviluppato un linguaggio di programmazione ad oggetti interno al navigatore chiamato JavaScript tramite il quale è possibile gestire le finestre del navigatore, i form di invio dati, la navigazione stessa delle pagine e tanto ancora. La Microsoft per il proprio navigatore Explorer ha realizzato un linguaggio molto simile chiamato JScript. Purtroppo i due linguaggi non sono compatibili al 100% anche se le istruzioni di base sono ben gestite da entrambi. Avere le idee chiare 2280 Figura 214.3. L’interprete PHP ha fatto il suo dovere. Questo è il codice generato e fornito al navigatore tramite il servente HTTP. Una volta ricevuta la richiesta della pagina da parte del navigatore, il servente inizia a leggere il file ‘primo.php’ e a inviarlo al cliente, appena trovati i marcatori ‘<?php.?>’ capisce che deve farsi «tradurre» il codice in essi contenuto. Lo passa quindi all’interprete PHP che lo esegue e restituisce il risultato. In questo semplice esempio il risulato dell’operazione è la stringa ‘23-03-2002’. La funzione utilizzata nell’esempio ‘date("d-m-Y")’ formatta la data nello schema giorno mese -anno (numerico), mentre ‘echo’ visualizza a schermo il risultato della funzione ‘date()’. Una modifica interessante al file precedente è: 1 <html> 2 <head> 3 <title>La mia prima pagina php</title> 4 </head> 5 <body> 6 7 <br><br> 8 9 <?php phpinfo() ?> 10 11 <br><br> 12 13 <a href="../cap_2/benvenuto.php">vai a benvenuto.php >></a> 14 15 </body> 16 </html> Questa volta il risultato è una pagina che visualizza la configurazione dell’elaboratore servente , dell’interprete e dei componenti per l’interrogazione delle basi di dati, oltre a una serie di variabili predefinite. È bene dare un’occhiata al sorgente HTML della pagina, tutta opera dell’interprete PHP. «immerso nel codice HTML»: con ciò si intende che quanto contenuto tra i marcatori ‘<?php.?>’ viene prima interpretato, e poi inviato al navigatore come semplice codice HTML insieme al resto della pagina. Avere le idee chiare 2281 214.2 Cosa può fare il PHP? Dunque il PHP permette di rendere dinamiche le pagine HTML dal lato del servente. Questo insieme alla sua semplicità di utilizzo, alla somiglianza con la sintassi C e alle innumerevoli funzioni che permettono di interagire con basi di dati e servizi di ogni genere ne hanno decretato il successo in Internet. La diffusione è dovuta alla semplicità di configurazione e alla completa compatibilità con numerosi serventi HTTP. Per il test degli script di questa guida è stato utilizzato come servente Apache. 2 Il PHP permette, in modo semplice e diretto, di far interagire il cliente con le basi di dati ospitate sul servente tramite il semplice utilizzo di un comune navigatore. Tutti i maggiori DBMS sono gestiti da PHP, senza dover installare software aggiuntivo o commerciale. Un breve elenco è riportato nella tabella 214.1. Tabella 214.1. Queste le basi di dati gestite dal PHP. BASI DI DATI Adabas D dBase Empress FilePro (read-only) IBM DB2 Informix Oracle (OCI7 and OCI8) InterBase FrontBase mSQL Direct MS-SQL MySQL ODBC PostgreSQL Solid Sybase Velocis Unix dbm Ingres Inoltre il PHP permette di interagire con numerosi servizi tramite i protocolli: IMAP, SNMP, NNTP, POP3, HTTP e molti altri. 214.3 PHP su piattaforma Microsoft Il PHP è compatibile con molte piattaforme di sviluppo, tra cui quella Microsoft. Ovviamente le migliori prestazioni si ottengono in ambiente GNU/Linux (o più in generale su sistemi Unix). Per informazioni più dettagliate si rimanda al sito ufficiale <http://www.php.net>. 214.4 Quanto costa il PHP? Il PHP viene distribuito nei termini della: The PHP License, version 2.02. I requisiti minimi richiesti all’eleboratore servente sono del tutto abbordabili. Per i test degli script contenuti in questa guida è stato utilizzato un vecchio P-120MHz con soli 16.Mibyte di RAM e un piccolo disco fisso da 1,2.Gibyte. Su di esso è stata installata una versione Debian GNU/Linux 2.2 con servente Apache, MySql, interprete PHP4. Sulla stessa macchina erano in esecuzione il servente FTP, PostgreSQL, Postfix e altri servizi minori. Programmare in PHP --- Copyright © 2001-2002 Gianluca Giusti -- brdp @ urcanet.it 2 è possibile prelevare Apache dal sito ufficiale <http://www.apache.org>. Capitolo 215 Le basi del linguaggio Per poter scrivere codice in un qualunque linguaggio è necessario conoscerne la sintassi. In questo capitolo verranno trattate le espressioni fondamentali del PHP con il supporto di script di esempio. 215.1 La sintassi In realtà ‘<?php ?>’ non sono gli unici marcatori per fornire codice all’interprete. Ecco tutti i modi di includere codice PHP negli script: • <? • <?php • <script language="php"> • <% codice ?> codice codice ?> codice </script> %> Il primo è disponibile solo se sono stati impostati i marcatori abbreviati, ciò può essere fatto abilitando nel file di configurazione ‘php.ini’ l’opzione ‘short_open_tag’. Per i particolari sugli altri marcatori si rimanda al manuale ufficiale. Va sottolineato che il codice può essere bloccato e ripreso in ogni punto dello stesso file, ad esempio: 1 <html> 2 <head> 3 4 <? $nome = "BRDP"; ?> 5 <title>ancora agli inizi</title> 6 7 </head> 8 <body> 9 10 <br>Ciao a tutti questo è il mio nome: <?=$nome ?> 11 12 </body> 13 </html> Nell’esempio il codice viene aperto per la prima volta nella riga 4, viene assegnato un valore alla variabile ‘$nome’, viene chiuso e poi riaperto nella riga 10 dove viene visualizzato a schermo il valore della variabile insieme a una frase HTML. Il file quindi restituirà come output la stringa: Ciao a tutti questo è il mio nome: BRDP Con l’occasione, nell’esempio, sono stati toccati due concetti base. Il primo è che le variabili in PHP iniziano con il carattere ‘$’ e sono sensibili a maiuscole e minuscole, l’altro è che non è necessario definirne il tipo, sarà quello del primo dato ad essa assegnato. Nel nostro caso la variabile ‘$nome’, dalla riga 4 in poi, sarà considerata una stringa. Per averne conferma basta sostituire il codice della riga 4 con le due righe seguenti: 4 5 6 7 <? $nome = "BRDP"; echo gettype($nome); ?> Il risultato è: string Ciao a tutti questo è il mio nome: BRDP 2282 Le basi del linguaggio 2283 Più avanti si apprenderà come trattare i vari tipi di dati, quindi è inutile dilungarsi in questo esempio; bisogna però dire che è possibile cambiare il tipo di dati mediante l’istruzione: settype($variabile, tipo_variabile); e ottenere il tipo di dato contenuto in una variabile tramite: gettype($variabile); Il secondo concetto è nella riga 10; per visualizzare il contenuto della variabile è stata utilizzata la sintassi: <?=$nome ?> Per chi si avvicina al PHP dopo aver sviluppato in Perl o in altri linguaggi script CGI la differenza è lampante. Non è necessario scrivere codice per generare HTML, semplicemente si inserisce codice PHP tra i marcatori HTML. Inoltre nel caso in cui l’istruzione sia la semplice visualizzazione di una singola variabile, la sintassi classica: <? echo $nome ?> può essere abbreviata con: <?=$nome ?> Attenzione: se il codice PHP è formato da più istruzioni consecutive è richiesto il carattere punto e virgola (‘;’) alla fine di ognuna di esse, se invece l’istruzione da inserire è una sola, il ‘;’ può essere omesso. Sarebbe buona norma dedicare molta cura all’indentazione del codice e inserire commenti chiari e diretti; così facendo si rende il codice più leggibile e comprensibile. La gestione dei commenti è simile a quella utilizzata in C, C++ e shell di Unix. I caratteri di commento sono: per una singola riga ‘//’ la barra obliqua doppia oppure il carattere ‘#’, per più righe il commento viene aperto con ‘/*’ e chiuso con ‘*/’. Nel secondo caso bisogna fare attenzione a non annidare i commenti. Questo è il modo corretto: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <? // Questo è un commento su una singola riga // adesso visualizzo ciao mondo! echo "ciao mondo!"; /* questo è un commento su più righe, posso scrivere di tutto!!! anche istruzioni php che non verranno interpretate come: echo "questo non verrà visualizzato!"; chiudo il commento */ echo "<br>questo invece si vedrà!!"; /* Notare che ho inserito <br> un marcatore html nel codice php! Posso farlo. */ ?> Questo è sbagliato: 0 1 2 3 4 <? /* echo "ciao mondo!"; /* questo causa problemi! */ */ 2284 5 6 Le basi del linguaggio ?> 215.2 Primo script Come primo esempio verrà realizzata una pagina di riconoscimento del visitatore. Il PHP fornisce una serie di «variabili predefinite». Tra esse ce ne sono alcune fornite dal protocollo HTTP. Per l’elenco completo delle variabili predefinite è bene consultare il manuale ufficiale del PHP, molte di esse vengono visualizzate nella pagina generata dalla funzione ‘phpinfo()’ 1 Il primo passo è scegliere le variabili da utilizzare. Per questo semplice script verranno utilizzate: • ‘SERVER_NAME’: nome dell’elaboratore su cui risiede e viene eseguito lo script; • ‘HTTP_REFERER’: l’URI, se ne esiste uno, da cui proviene il visitatore; 2 • ‘HTTP_USER_AGENT’: il tipo di navigatore utilizzato dal visitatore; • ‘REMOTE_ADDR’: l’indirizzo IP dell’elaboratore cliente; • ‘SCRIPT_NAME’: il percorso dello script in esecuzione; è importante fare molta attenzione all’utilizzo di queste variabili, alcune di esse usate in modo superficiale potrebbero fornire informazioni utili ai malintenzionati. Ad esempio ‘DOCUMENT_ROOT’ fornisce la directory su file system in cui si trovano gli script PHP e i documenti del servizio HTTP. Informazioni di questo tipo è meglio tenerle riservate! Scelte le variabili va creato il nuovo file e salvato con il nome di ‘benvenuto.php’. La prima versione, la più rudimentale, è la seguente: 1 <html> 2 <head> 3 <title>Benvenuto!</title> 4 </head> 5 <body> 6 7 <br> La mia prima vera pagina in PHP.<br><hr> 8 9 <br><br> Informazioni sul server: 10 <br>Sei giunto su: <?=$SERVER_NAME ?> 12 <br>Stai eseguendo lo script: <?=$SCRIPT_NAME ?> 13 14 <br><br> Esaminiamo il client: 15 16 <br> Indirizzo IP: <?=$REMOTE_ADDR ?> 17 <br> Vedo che provieni da: <?=$HTTP_REFERER ?> 18 <br> Tipo di browser: <?=$HTTP_USER_AGENT ?> 19 20 </body> 21 </html> Salvato il file nella directory del servizio HTTP e richiamato dal navigatore si ottiene qualcosa simile a: 1 Nel caso in cui il servente sia Apache, le variabili HTTP nella pagina ‘phpinfo()’ vengono raccolte nella sezione «variabili di Apache» 2 Se si segue il percorso degli script proposti dalla guida, il visitatore arriverà da <http://www.urcanet.it/brdp/php_manual/ esempi/cap_1/primo.php> Le basi del linguaggio 2285 La mia prima vera pagina in PHP. Informazioni sul server: Sei giunto su: www.urcanet.it Stai eseguendo lo script: /brdp/php_manual/esempi/cap_2/benvenuto.php Esaminiamo il client: Indirizzo IP: 127.0.0.1 Vedo che provieni da: http://www.urcanet.it/brdp/php_manual/esempi/cap_1/primo.php Tipo di browser: Mozilla/5.0 (X11; U; Linux 2.4.2-2 i686; en-US; 0.7) Gecko/20010316 Anche questo esempio è disponibile in rete all’indirizzo: <http://www.urcanet.it/brdp/php_manual/ esempi/cap_2/benvenuto.php> Il risultato potrebbe essere incomprensibile per i visitatori meno esperti. Ad esempio, il tipo di navigatore non è molto chiaro. Gli strumenti fin qui trattati non permettono di fare molto per migliorare il risultato dello script. Più avanti questo esempio potrà essere ripreso per manipolare il risultato in modo da mostrare al visitatore dei messaggi più chiari. 215.3 Tipi di dati Il PHP gestisce quattro tipi scalari, due tipi composti e due tipi speciali di dati. Tabella 215.1. Questi i tipi di dati gestiti dal PHP. Scalari Composti Speciali ‘boolean’ ‘integer’ ‘double’ ‘string’ ‘array’ ‘object’ ‘resurce’ ‘NULL’ Come già accennato in precedenza, il tipo di una variabile può essere modificato in ogni momento con la funzione ‘settype($variabile,tipo)’ che restituisce un valore booleano vero o falso rappresentante l’esito dell’operazione. I possibili tipi da assegnare alla variabile sono: • ‘integer’ • ‘double’ • ‘string’ • ‘array’ • ‘object’ I criteri di conversione dei tipi sono molto importanti, il codice mostrato di seguito non provoca problemi. 0 1 2 3 4 5 6 7 8 9 <? $a = 231; // da questo momento in poi $a è un intero if(settype($a,double)){ /* Se l’operazione è riuscita il valore è TRUE quindi visualizza il testo seguente. Altrimenti salta alla fine dell’if riga 10. */ echo "<br>valore settato a double. Ecco il nuovo valore: "; echo $a; Le basi del linguaggio 2286 10 } 11 ?> Spiacevoli inconvenienti potrebbero verificarsi se si prova a convertire una stringa in un intero. Per una trattazione più approfondita di questo argomento si rimanda al manuale ufficiale. Un’altra funzione utile per la gestione dei tipi di dati è ‘gettype($variabile)’ che restituisce una stringa contenente il tipo della variabile a essa fornita. Questi i possibili valori restituiti dalla funzione: • ‘integer’ • ‘double’ • ‘string’ • ‘array’ • ‘object’ • ‘unknown type’ Ecco un semplice esempio di utilizzo della funzione ‘gettype()’: 0 1 2 3 4 5 6 7 8 9 <? $a = "brdp"; /* la variabile $a è stata inizializzata come stringa */ $tipo_a = gettype($a); echo "<br>La variabile è di tipo:"; echo $tipo_a; ?> Il risultato dello script sarà: La variabile è di tipo: string Dopo questa breve trattazione sulla gestione dei tipi di dati a disposizione nel PHP, è bene accennare alle caratteristiche di ognuno di essi. 215.3.1 integer Il tipo di dati ‘integer’ rappresenta tutti i numeri dell’insieme matematico degli interi. Z = {..., -2, -1, 0, 1, 2, ...} Quindi tutti i numeri interi, sia negativi che positivi, vengono gestiti dal PHP come tipi ‘integer’. Anche i corrispondenti valori in base otto e sedici vengono gestiti come gli interi. Ecco alcuni esempi tratti dal manuale ufficiale: <? $a $a $a $a = = = = 1234; -123; 0123; 0x1A; // // // // numero numero numero numero intero positivo intero negativo ottale (equivalente a 83 in decimale) esadecimale (equivalente a 26 in decimale) ?> Il limite massimo della dimensione dei valori interi dipende dall’architettura dell’elaboratore su cui si lavora. Le basi del linguaggio 2287 Nel PHP non esiste un tipo specifico per i numeri naturali.3 Essi vengono gestiti come ‘integer’. 215.3.2 boolean Il tipo di dati ‘boolean’ può assumere solo due valori, vero o falso. Questo tipo viene utilizzato frequentemente per la gestione degli errori. Molte funzioni, infatti, restituiscono un valore booleano che assume valore vero se l’operazione è andata a buon fine, falso se si è verificato un errore. Per assegnare il valore vero o falso a una variabile è sufficiente l’istruzione: $bit = True; In questo esempio alla variabile ‘$bit’ è stato assegnato il valore vero. Anche se l’istruzione ‘if’ non è ancora stata trattata, è necessario anticipare le metodologie di controllo sul valore della variabile. In PHP non è necessario (anche se è possibile) eseguire il controllo in questo modo: <? $bit = True; if($bit == "True"){ // $bit è vero echo " il valore è vero!"; } ?> Basta scrivere: <? $bit = True; if($bit){ // $bit è vero echo " il valore è vero!"; } ?> L’interprete riconosce il tipo di dato e controlla se è vero. Nei prossimi capitoli verranno approfondite le caratteristiche dell’istruzione ‘if’. 215.3.3 double Come è stato più volte ripetuto, il PHP non necessita della definizione dei tipi di dati che si vanno a utilizzare ma inizializza il tipo di variabile in base al primo valore a essa associato. I «numeri a virgola mobile» in PHP contengono i tipi conosciuti in altri linguaggi come: ‘floats’, ‘doubles’, ‘real’. È possibile inizializzare una variabile di tipo ‘double’ assegnandole valori formattati in uno dei seguenti modi: <? $a = 1.234; $a = 1.2e3; $a = 7E-10; ?> Anche per questo tipo, come per gli interi, la dimensione massima dipende dall’architettura dell’elaboratore su cui viene eseguito lo script. 3 I numeri naturali sono il sottoinsieme positivo dei numeri interi. Le basi del linguaggio 2288 215.3.4 string Una stringa è un insieme di caratteri. In PHP non ci sono limiti particolari di lunghezza per i dati di tipo ‘string’. Ci sono più modi di delimitare una stringa. Ecco i due più comuni: 0 1 2 3 4 5 6 7 8 9 <? // single quoted string $nome = ’Gianluca Giusti’; // double queoted string $nome = "Gianluca Giusti"; /* In entrambi i casi $nome viene inizializzata come stringa dall’interprete PHP */ ?> L’interprete PHP riconosce come carattere di escape il ‘\’ (barra obliqua inversa). 4 Di seguito riportiamo i caratteri più comuni, una tabella completa è contenuta nel manuale ufficiale. Tabella 215.2. Alcuni caratteri di escape per le stringhe PHP. Carattere \t \n \\ \" \$ Significato carattere tabulazione carattere di fine riga ‘\’ barra obliqua inversa ‘"’ doppio apice ‘$’ dollaro Ecco alcuni esempi di come gestire le stringhe. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <? // Valorizzo una variabile che servirà in seguito. $email = " brdp @ urcanet.it "; // Stringa semplice: $stringa = "Ecco. Questa è una stringa"; // Ad essa si possono concatenare altre stringhe alla fine $stringa = $stringa." con dell’altro testo aggiunto"; // che equivale a scrivere $stringa .= " con dell’altro testo aggiunto"; // Oppure all’inizio $stringa = "altro testo ancora ".$stringa; // Adesso si prende la prima lettera della stringa $prima = $stringa{0}; // Concatenazione multipla $stringa = $prima." - ".$stringa." <br><br> il mio email: ".$email; /* Test sui caratteri di escape. All’interno della stringa posso visualizzare il valore di una variabile ma per visualizzarne il nome devo "inibire" il carattere speciale $. Lo faccio con l’uso della barra obliqua inversa. Ecco come: */ $stringa = "Questo il valore di \$email: $email"; 4 il carattere di escape viene utilizzato per rappresentare caratteri speciali all’interno di una stringa, caratteri che potrebbero creare confusione all’interprete. Le basi del linguaggio 2289 27 28 // c’è differenza con: 29 $stringa = "Questo il valore di $email: $email"; 30 ?> L’esempio precedente non è completo. Per poter osservare i risultati delle varie operazioni a schermo è necessario modificare lo script. Questo semplice, ultimo passo è lasciato al lettore come esercizio. Il PHP fornisce un gran numero di funzioni dedicate alla gestione delle stringhe; uno dei punti di forza di questo linguaggio sta proprio nella semplicità con cui queste possono essere manipolate. Risulta inutile dilungarsi nella trattazione delle singole funzioni, esse verranno descritte negli esempi in cui saranno impiegate. Un elenco completo e dettagliato è contenuto nel manuale ufficiale alla sezione «String functions». 215.3.5 array Gli array possono essere creati tramite il costrutto ‘array()’ oppure tramite la valorizzazione degli elementi. A differenza dei classici linguaggi di programmazione, il PHP permette di indicizzare gli array non solo mediante interi non negativi, ma anche tramite stringhe. Per chi conosce il Perl il concetto è molto simile a quello degli array associativi. Di seguito la sintassi per creare un array tramite il costrutto ‘array()’. 0 1 2 3 4 5 6 <? array( [chiave =>] valore , ... ) // la chiave può essere un intero non negativo o una stringa // il valore può essere qualunque ?> La chiave è contenuta tra le parentesi quadre perchè può essere omessa, se non viene specificata viene incrementato il valore intero. La sintassi di associazione è molto semplice ed intuitiva, per le chiavi intere positive: ‘chiave => valore’, mentre per le chiavi di tipo stringa vanno aggiunte le doppie virgolette ‘"chiave " => valore’. Per visualizzare il contenuto dell’array è possibile utilizzare la semplice istruzione ‘print_r($array)’. Negli esempi seguenti si vedrà come questa funzione visualizza l’array. Ecco alcuni esempi. 0 1 2 3 <? $a = array( "a", "b", 44, "d", "e"); print_r($a); ?> L’istruzione ‘print_r($a)’ visualizzerà sullo schermo la struttura e il contenuto dell’array nel seguente modo: Array ( [0] => a [1] => b [2] => 44 [3] => d [4] => e ) L’indice dei valori è stato incrementato automaticamente. È bene tenere sempre presente che le chiavi degli array partono da 0 e non da 1. C’è la possibilità di specificare solo alcune chiavi e lasciare la gestione degli indici omessi all’interprete. 0 1 <? $a = array( "a", "b", "c", "d", 8=>"e", 4=>"f", "g", 3=>"h"); 2290 2 3 Le basi del linguaggio print_r($a); ?> Questo il risultato dello script precedente: Array ( [0] => a [1] => b [2] => c [3] => h [8] => e [4] => f [9] => g ) A prima vista il risultato può sembrare errato, ma non è così. L’interprete incrementa automaticamente gli indici omessi dei primi quattro valori, ossia da 0 a 3, e mano a mano valorizza l’array. La lettera ‘e’ va invece inserita nella cella con chiave, specificata, pari a 8 e la ‘f’ in quella con chiave 4. Per la lettera ‘g’ non viene specificata nessuna chiave, l’interprete, quindi, riparte automaticamente dall’indice intero più alto incrementandolo di uno e ottiene il valore 9. Rimane da inserire l’ultima lettera ‘h’ che va, come richiesto, nella cella con chiave pari a 3. Questa operazione sovrascrive la lettera ‘d’ che già era stata inserita, in automatico, con chiave pari a 3. A questo punto dovrebbero essere chiari i motivi dell’assenza della lettera ‘d’ e del particolare ordine con cui vengono visualizzati i valori contenuti nell’array. Un array può essere creato anche senza l’utilizzo del costrutto ‘array()’, in questo caso la sintassi ricorda quella dei più comuni linguaggi di programmazione. Di seguito sono riportati gli esempi precedenti con l’utilizzo del secondo metodo di creazione. 0 1 2 3 4 5 6 7 <? $a[] = "a"; $a[] = "b"; $a[] = 44; $a[] = "d"; $a[] = "e"; print_r($a); ?> Il secondo esempio può essere tradotto in questo modo: 0 <? 1 $a[] = "a"; 2 $a[] = "b"; 3 $a[] = "c"; 4 $a[] = "d"; 5 $a[8] = "e"; 6 $a[4] = "f"; 7 $a[] = "g"; 8 $a[3] = "h"; 9 print_r($a); 10 ?> I due procedimenti per la creazione degli array sono equivalenti. Gli array possono avere chiavi miste, come nell’esempio seguente, in cui alcune sono intere e alcune stringhe. 0 1 2 3 4 5 6 7 <? $a["rosso"] = "a"; $a[] = "c"; $a[8] = "e"; $a["nero"] = "f"; $a[] = "g"; print_r($a); ?> Ecco il risultato: Array ( [rosso] => a [0] => c [8] => e [nero] => f [9] => g ) è interessante studiare una possibile applicazione pratica degli array. Nel seguente esempio verrà ripresa la funzione ‘date()’ già incontrata nella sezione 214.1. Le basi del linguaggio 2291 0 <? 1 // valorizzo l’array dei giorni della settimana con il metodo classico. 2 $giorno[0] = "Domenica"; 3 $giorno[1] = "Lunedì"; 4 $giorno[2] = "Martedì"; 5 $giorno[3] = "Mercoledì"; 6 $giorno[4] = "Giovedì"; 7 $giorno[5] = "Venerdì"; 8 $giorno[6] = "Sabato"; 9 10 // valorizzo l’array dei mesi dell’anno con il costrutto array() 11 $mese = array( 12 1 => "Gennaio", 13 2 => "Febbraio", 14 3 => "Marzo", 15 4 => "Aprile", 16 5 => "Maggio", 17 6 => "Giugno", 18 7 => "Luglio", 19 8 => "Agosto", 20 9 => "Settembre", 21 10 => "Ottobre", 22 11 => "Novembre", 23 12 => "Dicembre" 24 ); 25 // Prendo il mese in formato numerico da 1 a 12. 26 $numero_mese = date("n"); 27 28 /* Prendo il giorno della settimana da 0 (domenica) a 6 (sabato) 29 questa volta formatto tutto annidando più funzioni. 30 in PHP è possibile! */ 31 $giorno_settimana = $giorno[date("w")]; 32 33 // Formatto la data nel modo: Lunedì 19 Novembre 2001 34 $oggi = $giorno_settimana." ".date("d")."-".$mese[$numero_mese]."-".date("Y"); 35 36 // Visualizzo la data a schermo concatendandola ad una stringa 37 echo "<br> Oggi è: <b>".$oggi."</b>"; 38 ?> Il risultato di questo script, raggiungibile presso <http://www.urcanet.it/brdp/php_manual/esempi/cap_2/ è: data.php>, Oggi è: Domenica 18-Novembre-2001 Gli array rappresentano una delle strutture più versatili in PHP, a differenza dei linguaggi classici, infatti, la dimensione non deve essere specificata a priori. Questo permette una dinamicità e una libertà di utilizzo notevole. Il PHP gestisce anche gli array multidimensionali e gli array annidati. Non si entrerà nel merito, si darà per scontata la teoria sulla gestione degli array, che è simile per i diversi tipi di linguaggi, mentre si tratterà la sintassi tramite uno script di esempio. Il seguente è un esempio sull’utilizzo degli array multidimensionali. 0 1 2 3 4 5 6 7 8 9 10 <html> <head> <title>Semplice Agenda telefonica statica</title> </head> <body> <? /* Un semplice esempio di array multidimensionale. Una rubrica telefonica. */ 2292 Le basi del linguaggio 11 12 $a["nome"][0] = "Gianluca"; 13 $a["cognome"][0] = "Giusti"; 14 $a["tel"][0] = "06/66666666"; 15 16 $a["nome"][1] = "Mirko"; 17 $a["cognome"][1] = "Simeoni"; 18 $a["tel"][1] = "07/77777777"; 19 20 $a["nome"][2] = "Fabio"; 21 $a["cognome"][2] = "Ferri"; 22 $a["tel"][2] = "08/88888888"; 23 24 /* 25 Adesso elenchiamo la rubrica. Lo faremo senza 26 utilizzare Nessuna struttura ciclica per non 27 confondere le idee 28 */ 29 30 ?> 31 32 <br> 33 34 <table border="1"> 35 <tr bgcolor="gray" > 36 <td>ID</td> 37 <td>Nome</td> 38 <td>Cognome</td> 39 <td>Telefono</td> 40 </tr> 41 <tr> 42 <td>0</td> 43 <td><?=$a[nome][0]?></td> 44 <td><?=$a[cognome][0]?></td> 45 <td><?=$a[tel][0]?></td> 46 </tr> 47 <tr> 48 <td>1</td> 49 <td><?=$a[nome][1]?></td> 50 <td><?=$a[cognome][1]?></td> 51 <td><?=$a[tel][1]?></td> 52 </tr> 53 <tr> 54 <td>2</td> 55 <td><?=$a[nome][2]?></td> 56 <td><?=$a[cognome][2]?></td> 57 <td><?=$a[tel][2]?></td> 58 </tr> 59 60 </table> 61 62 </body> 63</html> Una volta salvato il codice nella propria directory dei documenti del servizio HTTP si può verificare il risultato. Anche questo esempio è disponibile all’indirizzo: <http://www.urcanet.it/brdp/ php_manual/esempi/cap_2/agenda.php>,inoltre, il risultato è riportato in figura 215.1. Le basi del linguaggio 2293 Figura 215.1. La rubrica telefonica è stata formattata in una tabella HTML. Inutile dire che questo è solo un’esempio per prendere confidenza con la sintassi PHP relativa agli array e che esistono soluzioni migliori per il salvataggio dei dati. Più avanti nella guida si tratteranno i file e le basi di dati. Un esercizio molto utile lasciato al lettore è la realizzazione di uno script clone del precedente con l’utilizzo del costrutto ‘array()’ per la gestione dell’array utilizzato nella rubrica telefonica. Gli array di array verranno trattati nella sezione dedicata alla «programmazione avanzata in PHP», in quanto richiedono maggiore dimestichezza con il linguaggio. 215.3.6 object Una classe è una collezione di variabili e di funzioni dette metodi. Una volta definita la classe è possibile istanziare uno o più oggetti della stessa classe. Ognuno di essi è indipendente dagli altri. Una trattazione approfondita può essere trovata nella sezione «programmazione avanzata in PHP» di questa guida. 215.4 Operatori Il PHP gestisce numerosi tipi di operatori, di seguito sono elencate le caratteristiche principali dei tipi utilizzati più di frequente. Per una trattazione completa si rimanda il lettore al manuale ufficiale. Tabella 215.3. Questi alcuni degli operatori gestiti dal PHP. OPERATORI aritmetici controllo degli errori incemento e decremento assegnazione logici confronto Verranno analizzati singolarmente gli operatori riportati nella tabella 215.3. 215.4.1 Operatori aritmetici Nella tabella 215.4 sono riportati gli operatori aritmetici con le rispettive caratteristiche. Le basi del linguaggio 2294 Tabella 215.4. Le caratteristiche degli operatori aritmetici. Esempio $a + $b $a - $b $a * $b $a / $b Nome Addizione Sottrazione Moltiplicazione Divisione Risultato Somma tra $a e $b Differenza tra $a e $b Prodotto tra $a e $b Quoziente tra $a e $b Lo schema è stato preso dal manuale ufficiale, è molto chiaro e non ha bisogno di molte spiegazioni. Bisogna tenere ben presente che il tipo della variabile a cui si assegna il risultato dipende dal tipo dei due valori ‘$a’ e ‘$b’. 215.4.2 Operatori di assegnazione L’operatore fondamentale per l’assegnazione di un valore ad una variabile è ‘=’. La sintassi fondamentale è: 0 1 2 3 4 5 6 7 8 9 <? // assegno ad $a il valore intero 123 $a = 123; // assegno a $b il contenuto di $a $b = $a; // assegno una stringa alla variabile $c $c = "questa è una stringa"; ?> L’operatore ‘=’ può essere utilizzato insieme ad altri operatori elencati nell’esempio: 0 <? 1 // 2 $a 3 4 // 5 $b 6 7 // 8 $a 9 10 // 11 $a 12 13 // 14 $a 15 $a 16 $a 17 18 // 19 $a 20 21 // 22 $a 23 $b 24 25 // 26 $a 27 $a 28 29 // 30 $a 31 $a 32 ?> assegno ad $a un valore intero = 2; assegno a $b un altro valore intero = 5; posso assegnare a $a la somma di $a e $b in questo modo = $a + $b; oppure in questo modo += $b; stesso discorso per tutti gli operatori aritmetici -= $b; *= $b; /= $b; posso anche assegnare un valore a più variabili = $b = 30; o ancora in questo esempio sia $a che $b valgono 6 = 3; = $a += 3; per le stringhe. $a varrà "ciao a tutti!!!" = "ciao a"; .= " tutti!!!"; equivale a concatenare la stringa in questo modo = "ciao a"; = $a." tutti!!!"; Le basi del linguaggio 2295 I commenti inseriti nell’esempio dovrebbero bastare a descrivere la versatilità degli operatori appena trattati. 215.4.3 Operatori di controllo degli errori Nell’esempio seguente viene gestito un errore dovuto al tentativo di lettura di un file inesistente. Con l’occasione viene utilizzata la funzione PHP ‘file(’nome_del_file’)’ che restituisce un array contenente le righe del file passato alla funzione. 0 1 2 3 4 5 6 7 8 9 <? // provo ad aprire un file che non esiste $file_array = file(’file_inesistente’) or die (" Errore durante l’apertura del file. "); /* il file non esiste, lo script si ferma mostrando i messaggi di errore */ ?> Se si salva il codice in un file e si richiama tramite il navigatore, si nota che oltre al messaggio di errore inserito nello script viene visualizzato un messaggio introdotto dall’interprete PHP. I messaggi di errore possono contenere informazioni utili ai male intenzionati, è bene, quindi, gestire tali messaggi al meglio. Un esempio è riportato in figura 215.2 dove si nota il percorso su file system dello script di prova. Figura 215.2. Ecco come appare la pagina contenente l’errore non gestito. Oltre al messaggio di errore da noi inserito viene visualizzato anche un warning dall’interprete PHP. Un modo molto semplice per non far visualizzare i messaggi d’errore dell’interprete è premettere il carattere ‘@’ alla funzione. Ad esempio: ‘@file(’dati.txt’)’. L’esempio precedente potrebbe essere modificato in questo modo: 0 1 2 3 4 5 6 7 8 9 <? // provo ad aprire un file che non esiste $file_array = @file(’file_inesistente’) or die (" Errore durante l’apertura del file. "); /* In questo caso il messaggio di errore dell’interprete PHP è stato silenziato dalla ’@’ premessa alla funzione file(). Verrà quindi mostrato solo il nostro messaggio di errore */ ?> Il costrutto ‘die()’ non fa altro che terminare l’esecuzione del programma, in caso di errore, mostrando il messaggio contenuto tra le parentesi. Le basi del linguaggio 2296 215.4.4 Operatori di incremento e decremento Come detto, la sintassi PHP ricorda molto quella del C. Gli operatori di pre e post incrementazione sono gestiti come nel linguaggio C. Nella tabella 215.5 sono riportati i quattro operatori: Tabella 215.5. Questi gli operatori di incremento e decremento gestiti dal PHP. Esempio ‘$a++’ ‘++$a’ ‘$a--’ ‘--$a’ Nome Post-incremento Pre-incremento Post-decremento Pre-decremento Risultato Restituisce ‘$a’ e poi la incrementa di uno Incrementa di uno ‘$a’ e poi la restituisce Restituisce ‘$a’ e poi la decrementa di uno Decrementa di uno ‘$a’ e poi la restituisce Nell’esempio seguente vengono utilizzati i quattro operatori: 0 <? 1 $a = 1; 2 3 // Operatori di pre-incremento 4 5 echo "<br>La variabile vale: ".++$a; 6 echo " e dopo vale: ".$a; 7 8 // Operatori di post-incremento 9 10 echo "<br>La variabile vale: ".$a++; 11 echo " e dopo vale: ".$a; 12 13 // Operatori di pre-decremento 14 15 echo "<br>La variabile vale: ".--$a; 16 echo " e dopo vale: ".$a; 17 18 // Operatori di post-decremento 19 20 echo "<br> La variabile vale: ".$a--; 21 echo " e dopo vale: ".$a; 22 23 ?> Se si prova a salvare l’esempio in un file nella directory del servizio HTTP, una volta richiamato mediante il navigatore, il risultato sarà di questo tipo: La La La La variabile variabile variabile variabile vale: vale: vale: vale: 2 2 2 2 e e e e dopo dopo dopo dopo vale: vale: vale: vale: 2 3 2 1 Ragionando passo passo si capisce il lavoro dell’interprete e di conseguenza il risultato ottenuto. La variabile inizialmente vale 1. Nella riga 5 viene incrementata, prima di essere visualizzata, tramite l’operatore ‘++$a’. Nella riga 6 viene mostrato il valore di ‘$a’ senza eseguire alcuna operazione. Da queste prime due righe di codice si ottiene la riga: La variabile vale: 2 e dopo vale: 2 Nella riga 10, invece, viene utilizzato l’operatore ‘$a++’ che prima visualizza il contenuto della variabile e poi lo incrementa. Infatti la riga 11 restituisce un valore di ‘$a’ pari a 3. Il risultato è evidente nella seconda riga del file HTML generato dallo script di prova. Stessa procedura per gli operatori di pre e post decremento, fino a ritornare al valore iniziale della variabile. Le basi del linguaggio 2297 215.4.5 Operatori logici Gli operatori logici gestiti dal PHP sono riportati nella tabella 215.6. Tabella 215.6. Questi gli operatori logici gestiti dal PHP. Esempio ‘$a and $b’ ‘$a or $b’ ‘$a Xor $b’ ‘!$a’ ‘$a && $b’ ‘$a || $b’ Nome AND OR XOR NOT AND OR Risultato vera se $a e $b sono vere vera se $a o $b è vera vera se $a o $b è vera ma non entrambe Negazione. Vera se $a non è vera Simile a ‘and’ ma con precedenza diversa Simile a ‘or’ ma con precedenza diversa Le precedenze degli operatori sono riportate nel manuale ufficiale. In questo momento è inutile dilungarsi in esempi, gli operatori logici verranno approfonditi in seguito. In particolare verranno trattati con l’introduzione dell’istruzione ‘if’. 215.4.6 Operatori di confronto Il PHP gestisce tutti gli operatori di confronto riportati nella tabella 215.7. Tabella 215.7. Gli operatori di confronto gestiti dal PHP. Esempio ‘$a ‘$a ‘$a ‘$a ‘$a ‘$a ‘$a ‘$a ‘$a == $b’ === $b’ != $b’ <> $b’ !== $b’ < $b’ > $b’ <= $b’ >= $b’ Nome Uguale Identico Diverso Diverso Non Identico Minore Maggiore Minore o uguale Maggiore o uguale Risultato vera se $a è uguale a $b vera se $a è uguale a $b e sono dello stesso tipo vera se $a è diverso da $b vera se $a è diverso da $b vera se $a non è uguale a $b o non sono dello stesso tipo vera se $a è minore di $b vera se $a è maggiore di $b vera se $a è minore o uguale a $b vera se $a è maggiore o uguale a $b Esempi pratici sugli operatori di confronto verranno trattati in seguito, nella guida, con l’introduzione delle «strutture di controllo». 215.5 Strutture di controllo Nella tabella 215.8 sono riportate le strutture di controllo che verranno trattate in dettaglio nelle pagine seguenti. Tabella 215.8. Le strutture di controllo. Strutture if else elseif switch di controllo while do..while for foreach break include() le strutture di controllo sono state raggruppate per tipologia e ordinate secondo la difficoltà. Di seguito verranno trattati prima i costrutti più semplici e poi quelli più complessi. 2298 Le basi del linguaggio Nella prima colonna sono raccolte le strutture tramite le quali si è in grado di eseguire determinate istruzioni al verificarsi di particolari condizioni. Nella seconda colonna sono raccolte le strutture mediante cui è possibile realizzare e gestire delle operazioni cicliche, fino a quando una particolare condizione viene soddisfatta e interrompe il ciclo. In questo ultimo caso è importante tenere sempre presente la condizione di STOP. Questo per evitare dei cicli infiniti che possono bloccare il funzionamento del programma. Inoltre negli esempi che seguono verranno utilizzati gli operatori precedentemente introdotti. 215.5.1 if Il costrutto ‘if’ è molto importante e utilizzato in tutti i linguaggi di programmazione. La sintassi è la seguente: if(condizione) singola istruzione Utilizzato in questo modo, solamente un’istruzione è condizionata dall’esito della condizione contenuta nel costrutto ‘if’. Ecco un esempio: 0 <? 1 $a = 3; 2 $b = 5; 3 4 if($a < $b) // uso un operatore di confronto 5 echo "Condizionato da if. Solo se \$a è minore di \$b."; 6 7 echo "<br>Questo, invece, viene scritto comunque!!!"; 8 9 ?> Se si ha bisogno di condizionare una o più istruzioni la sintassi da utilizzare è la seguente: if(condizione){ istruzione 1 istruzione 2 . . . istruzione n } Riprendendo l’esempio precedente si può scrivere: 0 <? 1 $a = 3; 2 $b = 5; 3 4 if($a < $b){ 5 echo "Istruzione 1."; 6 echo "Istruzione 2."; 7 echo "Istruzione 3."; 8 } 9 10 echo "<br>Questo, invece, viene scritto comunque!!!"; 11 12 ?> La differenza è semplice e lampante. Il blocco delle istruzioni condizionate va contenuto tra le parentesi ‘{ }’. Le basi del linguaggio 2299 215.5.2 else Nell’ultimo esempio viene gestito un solo evento. Se si volesse gestire anche l’evento $a >= $b si potrebbe aggiungere, in modo poco elegante e funzionale, un altro ‘if($a >= $b){ istruzioni }’. Tuttavia la soluzione più corretta è sicuramente l’utilizzo della struttura ‘else’ La sintassi del costrutto ‘else’ è la seguente: if(condizione){ istruzione 1 istruzione 2 . . . istruzione n }else{ istruzione 1 istruzione 2 . . . istruzione m } Di seguito sono riportati alcuni esempi per chiarirne l’utilizzo e per prendere confidenza con gli operatori precedentemente trattati. 0 <? 1 2 if(!$a){ // $a è falso. 3 $a = "ok"; 4 }else{ 5 $a = "ko"; 6 } 7 8 // a questo punto $a vale "ok" 9 10 if($a == "ok"){ 11 echo "Sono entrato nell’if e \$a vale: ".$a; 12 echo "<br> Adesso cambiamo il contenuto di \$a"; 13 $a = 17; 14 }else{ 15 echo "\$a non vale \"ok\" e quindi mi trovo nell’else. \$a: ".$a; 16 echo "<br> anche in questo caso setto \$a uguale a 17 ma in modo diverso."; 17 $a = 16; 18 $a += 1; 19 } 20 21 // adesso scrivo il tipo e il valore di $a 22 23 if(is_integer($a)){ 24 echo "<br> \$a è un INTERO e vale: ".$a; 25 }else{ 26 echo "<br> \$a NON è un intero e vale: ".$a; 27 } 28 29 ?> Lo script, così come nell’esempio, restituisce un risultato simile al seguente: Sono entrato nell’if e $a vale: ok Adesso cambiamo il contenuto di $a Le basi del linguaggio 2300 $a è un INTERO e vale: 17 Per comprendere al meglio il flusso del programma e delle strutture in esso contenute, si può inserire nella riga 1 la valorizzazione di ‘$a’, ad esempio: 1 $a = "qualche valore"; Così facendo l’esito del primo ‘if’ cambia e di conseguenza tutto il resto dello script. Con l’occasione si è utilizzata una nuova funzione, ‘is_integer()’, che restituisce un valore booleano vero se la variabile ad essa fornita è di tipo intero, falso se la variabile non è intera. Esistono altre funzioni simili per verificare il tipo delle variabili, tra cui: ‘is_array()’, ‘is_double()’, ‘is_string()’. Il funzionamento è analogo a quello di ‘is_integer()’. Ovviamente esistono altre funzioni di questo tipo e sono raccolte nella sezione «Funzioni di Variabili» del manuale ufficiale del PHP. 215.5.3 elseif Si supponga di dover gestire il confronto tra due variabili ‘$a’ e ‘$b’ di tipo intero. I possibili risultati del confronto sono tre: • $a > $b • $a < $b • $a = $b Utilizzando le strutture viste fino ad ora, non si è in grado di risolvere il problema. Una soluzione poco elegante, e sicuramente non ottimale, è eseguire tre ‘if’ in cascata. Per risolvere problemi di questo tipo il PHP mette a disposizione la struttura ‘elseif’. La sintassi è analoga a quella di ‘else’. if(condizione){ istruzione 1 istruzione 2 . . . istruzione n }elseif(condizione){ istruzione 1 istruzione 2 . . . istruzione m }else{ istruzione 1 istruzione 2 . . . istruzione k } Ecco come applicare la sintassi all’esempio precedentemente descritto: Le basi del linguaggio 2301 0 <? 1 $a = 3; // valorizzo la variabile $a a mio piacere 2 $b = 6; // valorizzo la variabile $b a mio piacere 3 4 // adesso eseguo il confronto con un unica istruzione elseif 5 6 if ($a > $b) { 7 echo " \$a è maggiore di \$b "; 8 } elseif ($a == $b) { 9 echo " \$a è uguale a \$b "; 10 } else { 11 echo " \$a è minore di \$b "; 12 } 13 14 ?> Dunque in questo modo si è in grado di gestire più condizioni. Il flusso è molto semplice e intuitivo. Se una delle due condizioni è soddisfatta l’interprete esegue le istruzioni ad essa associate ed esce dal blocco ‘elseif’. Se è presente un ‘else’ finale e nessuna condizione è stata soddisfatta, l’interprete ne esegue le istruzioni e lascia il blocco ‘elseif’. Va precisato che viene eseguito al massimo un blocco di istruzioni. Se più condizioni sono soddisfatte, solo le istruzioni associate alla prima condizione vera vengono eseguite, le altre vengono saltate. Si può inserire più di un ‘elseif(condizione)’ all’interno della struttura. Vediamo come, modificando l’esempio precedente. 0 <? 1 $a = 3; // valorizzo la variabile $a a mio piacere 2 $b = 6; // valorizzo la variabile $b a mio piacere 3 4 // adesso eseguo il confronto con un unica istruziione elseif 5 6 if ($a > $b) { 7 echo " \$a è maggiore di \$b "; 8 } elseif ($a === $b) { 9 echo "\$a è identica a \$b"; 10 } elseif ($a == $b) { 11 echo " \$a è uguale a \$b "; 12 } else { 13 echo " \$a è minore di \$b "; 14 } 15 16 ?> Per verificare la correttezza e capire il diverso funzionamento, si provi ad assegnare alla variabile ‘$b’ i seguenti valori: • $b = 6; • $b = 3; • $b = 3.0; Infine si modifichino le righe interessate allo script di esempio nel seguente modo: 8 9 10 11 } elseif ($a == $b) { echo "\$a è uguale a \$b"; } elseif ($a === $b) { echo " \$a è identica a \$b "; Le basi del linguaggio 2302 In questo modo la voce ‘$a è identica a $b’ non viene mai visualizzata. Al lettore il semplice compito di scoprirne il motivo. 5 215.5.4 switch Spesso ci si trova a dover confrontare il contenuto di una variabile con più valori, in questi casi è preferibile utilizzare la struttura ‘switch’ al posto di ‘elseif’. Un esempio renderà più chiaro il concetto. Si supponga di dover gestire un menu. In base al valore di una variabile vengono eseguite una o più operazioni. Nell’esempio la variabile ‘$scelta’ è valorizzata nella riga 2. Per provare il funzionamento del programma basterà cambiare il valore a questa variabile. 0 <? 1 // valorizzo la variabile $scelta 2 $scelta = 0; 3 4 // con switch gestisco i confronti e le operazioni. 5 6 switch ($scelta) { 7 case 0: 8 echo "<br> lancio l’istruzione associata al valore 0 "; 9 break; // esce da switch 10 case 1: 11 echo "<br> lancio l’istruzione associata al valore 1 "; 12 break; // esce da switch 13 case 2: 14 echo "<br> lancio l’istruzione associata al valore 2 "; 15 break; // esce da switch 16 default: 17 echo "<br> NESSUNA OPERAZIONE ASSOCIATA alla scelta"; 18 19 } 20 21 ?> Nella struttura ‘switch’ a differenza di ‘elseif’, l’interprete esegue le istruzioni successive al ‘case’ soddisfatto. Questo è il motivo per cui si utilizza il comando ‘break’. Più avanti si tratterà questo costrutto, per il momento basta sapere che serve ad abbandonare la struttura di controllo. L’esempio precedente genera un risultato di questo tipo: lancio l’istruzione associata al valore 0 Se non ci fossero i ‘break’ in ogni blocco di istruzione il risultato sarebbe: lancio l’istruzione associata al valore 0 lancio l’istruzione associata al valore 1 lancio l’istruzione associata al valore 2 NESSUNA OPERAZIONE ASSOCIATA alla scelta Se il funzionamento di ‘switch’ non risulta ancora chiaro, si provi, dopo aver tolto le istruzioni ‘break’, ad assegnare alla variabile ‘$scelta’ i valori: 0,1 e 2, verificandone i singoli risultati. Nel caso di più uguaglianze la differenza tra ‘switch’ e ‘elseif’ è minima, in questi casi, l’utilizzo di ‘switch’ risulta più elegante e leggibile di ‘elseif’. Di seguito viene riportato l’esempio precedente riscritto utilizzando la struttura elseif. 0 1 <? // valorizzo la variabile $scelta 5 La condizione di identità include quella di uguaglianza, quindi, se due variabili sono identiche di conseguenza sono anche uguali, mentre non è vero il contrario. Ecco perchè bisogna fare attenzione all’ordine in cui si scrivono le condizioni. Le basi del linguaggio 2303 2 $scelta = 0; 3 4 // adesso utilizzo elseif per gestire le operazioni 5 6 if($scelta == 0) { 7 echo "<br> lancio l’istruzione associata al valore 0 "; 8 }elseif($scelta == 1){ 9 echo "<br> lancio l’istruzione associata al valore 1 "; 10 }elseif($scelta == 2){ 11 echo "<br> lancio l’istruzione associata al valore 2 "; 12 }else{ 13 echo "<br> NESSUNA OPERAZIONE ASSOCIATA alla scelta"; 14 } 15 16 ?> 215.5.5 while Il ‘while’ è la struttura di gestione dei cicli più semplice del PHP. La traduzione in italiano è: "mentre". La sintassi è la seguente: while(condizione){ istruzione 1 istruzione 2 . . . istruzione n } Cioè: «MENTRE la condizione è vera esegui le istruzioni». Il seguente esempio può aiutare a chiarire le idee. 0 1 2 3 4 5 6 <? $i=1; while ($i <= 6){ // mentre $i è minore o uguale a 7 echo "<br> \$i adesso vale: ".$i; $i++; } ?> Dunque, in questo caso la condizione di stop, che fa fermare il ciclo, è ‘$i > 6’. Ovvero ‘$i <= 6’ è falsa. Il risultato è il seguente: $i $i $i $i $i $i adesso adesso adesso adesso adesso adesso vale: vale: vale: vale: vale: vale: 1 2 3 4 5 6 Tramite un semplice ciclo PHP si può generare una pagina HTML come quella riportata in figura 215.3 Le basi del linguaggio 2304 Figura 215.3. Questo è stato generato dal ciclo ‘while’. Semplicemente è stato eseguito il seguente codice: 0 <html> 1 <head> 2 <title>Ciclo while</title> 3 </head> 4 <body> 5 6 <br> Un ciclo WHILE<br><hr> 7 8 <? 9 $i=1; 10 while ($i <= 6){ 11 ?> 12 13 <br> <font size="<?=$i?>">Questo è un font con size = <?=$i?></font> 14 15 <? 16 $i++; 17 } 18 ?> 19 20 21 </body> 22 </html> Dal menu visualizza del navigatore, l’opzione sorgente 0 <html> 1 <head> 2 <title>Ciclo while</title> 3 </head> 4 <body> 5 <br> Un ciclo WHILE<br><hr> 6 7 <br> <font size="1">Questo è 8 <br> <font size="2">Questo è 9 <br> <font size="3">Questo è 10 <br> <font size="4">Questo è 11 <br> <font size="5">Questo è 12 <br> <font size="6">Questo è 13 14 </body> 15 </html> un un un un un un font font font font font font con con con con con con pagina, size size size size size size = = = = = = mostra il seguente codice: 1</font> 2</font> 3</font> 4</font> 5</font> 6</font> Le righe dalla 7 alla 12 sono state generate dall’interprete con l’esecuzione del ciclo ‘while’ dell’esempio. Le basi del linguaggio 2305 215.5.6 do..while A differenza del ‘while’ il ‘do..while’ esegue il controllo sulla condizione dopo l’esecuzione delle istruzioni. Ecco la sintassi: do { istruzione 1 istruzione 2 . . . istruzione n }while(condizione); Dunque l’interprete esegue le istruzioni e solo dopo controlla la condizione di stop, se è vera riesegue le istruzioni, se è falsa abbandona il ciclo. Di seguito è riportato un esempio costituito da due cicli, uno utilizza il costrutto ‘do..while’, l’altro il ‘while’. Le condizioni iniziali e di uscita sono le stesse ma il risultato è diverso. Al lettore il compito di capire tali differenze. 0 <? 1 // Condizione iniziale! 2 $inizio = 0; 3 4 // ciclo do..while 5 6 do{ 7 echo "<br> ciclo: do..while. \$inizio vale: ".$inizio; 8 }while($inizio > 0); 9 10 // mentre il ciclo while 11 12 while($inizio > 0){ 13 echo "<br> ciclo: while. \$inizio vale: ".$inizio; 14 } 15 ?> 215.5.7 for La sintassi del ciclo ‘for’ può sembrare incomprensibile ad una prima lettura, invece è molto coincisa, versatile e, con un po’ di pratica, semplice. Eccola: for(condizione istruzione istruzione . . . istruzione } iniziale; condizione stop; variazione parametro){ 1 2 n Tale sintassi viene applicata nel seguente modo: for($i=0; $i<10; $i++){ echo "<br>tutte le istruzioni che desidero"; } Il codice dell’esempio può essere letto come: «partendo da $i = 0, mentre $i<10 esegui le istruzioni e incrementa $i di uno ». Sia le condizioni che la variazione possono essere omesse o incluse tra le istruzioni. Per il momento verrà trattata la sintassi classica. Il modo più semplice e diretto è, come al solito, un esempio ben commentato. 2306 Le basi del linguaggio 0 <? 1 // sintassi classica: 2 3 for($i=0; $i<10; $i++){ 4 echo "<br> non serve incrementare, lo fa il for"; 5 echo "<br> infatti ecco il valore di \$i: ".$i; 6 } 7 8 // se ho una sola istruzione, come con l’if 9 10 for ($i=0; $i<10; $i++) 11 echo "<br> per una sola va bene così. \$i vale: ".$i; 12 13 // oppure se è solo un print 14 15 for($i=0; $i<10; print"<br>".$i, $i++) 16 17 // Ancora posso incrementare $i tra le istruzioni 18 19 for($i=0; $i<10; ){ 20 echo "<br>incrementare \$i altrimenti il ciclo è infinito. \$i=".$i; 21 $i++; 22 } 23 24 // Oppure premetto la condizione iniziale. 25 26 $i=0; 27 for( ; $i<10; $i++){ 28 echo "<br>eccolo : ".$i; 29 } 30 31 ?> Come detto è possibile omettere anche le condizioni iniziale e di stop. Per fare questo è necessario utilizzare la struttura ‘break’ che verrà introdotta nelle pagine seguenti. In quell’occasione verranno trattate tali eccezioni. A questo punto, un ottimo esercizio per il lettore è la traduzione degli esempi visti per le strutture del ‘while’ e ‘do..while’, in script uguali o simili utilizzando le varie derivazioni del costrutto ‘for’. 215.5.8 foreach Va subito notato che il costrutto ‘foreach’ è stato implementato dalla versione 4.0 in poi e quindi non è gestita dalle versioni precedenti del PHP. L’uso del ‘foreach’ è indicato per la gestione degli array e mette a disposizione due sintassi principali: foreach($variabile_array as $value){ .... istruzioni .... } e: foreach($variabile_array as $key => $value){ ... istruzioni ... } Le basi del linguaggio 2307 il suo funzionamento, a differenza del semplice ‘for’, non è molto intuitivo ed è vincolato all’utilizzo di un array. Si nota immediatamente che la sintassi non richiede l’utilizzo di indici ne di incrementi, infatti il costrutto opererà su tutti gli argomenti dell’array indistintamente. Dunque questo strumento risulta comodo e versatile quando si ha a che fare con array con chiavi particolari o non consecutive (nel caso di chiavi numeriche). Si supponga di avere un primo array composto da chiavi intere e consecutive simile al seguente: <? $array_1 = array (1, "a", 5, "c", "ciao"); print_r($array_1); ?> // con chiavi da 0 a 4 e un secondo composto da chiavi miste e quindi non consecutive come questo: <? $array_2 = array ( "uno" => 1, "frutta" => "mela", 5 => "cinque", 40 => 30 ); print_r($array_2); ?> // // // // chiave chiave chiave chiave stringa e valore intero stringa e valore stringa intero e valore stringa intero e valore intero I risultati dei due script sono semplicemente: Array ( [0] => 1 [1] => a [2] => 5 [3] => c [4] => ciao ) Array ( [uno] => 1 [frutta] => mela [5] => cinque [40] => 30 ) Si supponga ora di non conoscere le chiavi del secondo array perchè assegnate dinamicamente da un codice precedente. In questo caso non si sarebbe in grado di operare sull’array con le strutture cicliche classiche perchè non c’è nessuna relazione tra le chiavi. Mentre nel primo la relazione tra le chiavi è semplice, sono interi successivi a partire da 0. In queste situazioni la struttura ‘foreach’ è tanto indispensabile quanto semplice ed immediata da utilizzare. L’esempio potrebbe continuare con la necessità di separare i valori interi da quelli non interi, contenuti in ‘$array_2’. Di seguito viene risolto il problema con l’utilizzo del costrutto ‘foreach’ e della prima sintassi. 0 <? 1 foreach ($array_2 as $val) { 2 echo "<br>\$val = ".$val; 3 if(is_integer($val)){ 4 echo " ------> ed è un intero..."; 5 // possono seguire istruzioni per trattare i dati interi 6 }else{ 7 echo " ------> ma non è un intero..."; 8 // possono seguire istruzioni per trattare i dati NON interi 9 } 10 } 11 ?> ‘foreach’ in italiano può essere tradotto come ‘per ogni’, dunque la sintassi è ora più chiara: per ogni valore dell’array ‘$array_2’ preso come ‘$val’ esegui le istruzioni associate. Il costrutto ad ogni ciclo valorizza la variabile ‘$val’ con un elemento dell’array. Ripete l’operazione per tutti gli elementi indipendentemente dalle chiavi ad essi associati. Nell’esempio le cose sono state complicate con l’annidamento di un ‘if’ che verifica ad ogni ciclo il tipo di dato estratto dall’array, il risultato è il seguente: $val = 1 ------> ed è un intero... $val = mela ------> ma non è un intero... Le basi del linguaggio 2308 $val = cinque ------> ma non è un intero... $val = 30 ------> ed è un intero... A questo punto è semplice dedurre il funzionamento della seconda sintassi, infatti, il ‘foreach’ può estrarre sia la chiave che il valore degli elementi contenuti nell’array. Complicando ulteriormente lo script precedente si può verificare il funzionamento della seconda sintassi. 0 <? 1 foreach ($array_2 as $chiave => $valore) { 2 echo "<br>\$val = ".$valore; 3 if(is_integer($valore)){ 4 echo " ------> ed è un intero..."; 5 echo " ------> questa la sua chiave: ".$chiave; 6 // possono seguire istruzioni per trattare i dati interi 7 }else{ 8 echo " ------> ma non è un intero..."; 9 echo " ------> questa la sua chiave: ".$chiave; 10 // possono seguire istruzioni per trattare i dati NON interi 11 } 12 } 13 ?> Sono state aggiunte le righe 5 e 9 che visualizzano il volore delle chiavi ed è stata modificata la sintassi della riga 1 in cui si chiede al ‘foreach’ di estrarre anche le chiavi degli elementi dell’array oltre al valore e di assegnarli alle variabili ‘$chiave’ e ‘$valore’. Il risultato è il seguente: $val $val $val $val = = = = 1 ------> ed è un intero... ------> questa la sua chiave: uno mela ------> ma non è un intero... ------> questa la sua chiave: frutta cinque ------> ma non è un intero... ------> questa la sua chiave: 5 30 ------> ed è un intero... ------> questa la sua chiave: 40 In conclusione il costrutto ‘foreach’ è una struttura ciclica dedicata alla manipolazione degli array. Ovviamente possono essere gestiti anche array multidimensionale con dei ‘foreach’ annidati, il lettore può approfondire l’argomento sul manuale ufficiale. L’esempio trattato è raggiungibile all’indirizzo: <http://www.urcanet.it/brdp/php_manual/esempi/cap_2/ foreach.php> 215.5.9 break Il costrutto ‘break’ serve ad abbandonare una struttura di controllo, nel dettaglio permette di uscire da: ‘for’, ‘foreach’, ‘while’, ‘do..while’ e ‘switch’, e ammette un parametro numerico opzionale. Tale parametro deve essere un intero che indicherà il "livello" della struttura da abbandonare. Ad esempio, nel caso di due o più strutture annidate, si potrebbe voler uscire da una o più di esse: questo è possibile tramite il parametro. Con l’occasione verranno approfondite, negli esempi seguenti, le strutture tralasciate in precedenza. 0 <? 1 2 $i = 0; 3 while (++$i) { // il while incrementa anche in questo modo 4 5 if($i == 3){ 6 7 echo "<br>Conto fino a ".$i." ed esco solo dal conteggio: "; 8 9 for ($t = 1; ;$t++) { // la condizione di stop è tra le istruzioni. 10 if ($t > $i) { 11 break 1; // esce solo dal for equivale a break senza parametri. 12 } Le basi del linguaggio 2309 13 echo " ".$t; 14 } 15 16 }elseif($i == 9){ 17 18 echo "<br> Conto fino a ".$i." ed esco dal for e dal while:"; 19 20 $t = 1; 21 for (;;) { // Nessuna condizione è espressa nel costrutto. 22 if ($t > $i) { 23 break 2; // il parametro è 2 quindi esce dal for e dal while. 24 } 25 echo " ".$t; 26 $t++; 27 } 28 29 } 30 31 } 32 33 echo "<br><br> fine dello script!"; 34 35 ?> Come detto in precedenza, è importante curare l’indentazione del codice. L’ultimo esempio è composto da un ciclo ‘while’ che include un ‘elseif’ e due cicli ‘for’ che, a loro volta, contengono un ‘if’ ciascuno. Tutto questo susseguirsi di parentesi può creare confusione e rendere il codice illegibile se non si presta attenzione all’indentazione. Nella maggior parte dei casi, se il codice è ben scritto e ragionato, non si ha bisogno della struttura ‘break’. Tuttavia è bene sapere che esiste. 215.5.10 include() Il PHP permette di includere uno o più file in un punto ben preciso di un altro file. Tali file possono, a loro volta, contenere codice PHP che verrà interpretato se delimitato dagli appositi marcatori. Si pensi alla gestione di modelli grafici, alla necessità di dichiarare le stesse variabili in più file, all’inclusione di funzioni già pronte e via dicendo. In tutti questi casi è possibile creare un file specifico in cui inserire il codice che va incluso negli script. Ovviamente è possibile includere anche file residenti su macchine diverse dalla nostra. Di seguito vedremo come fare. Per l’inclusione dei file il PHP offre diverse soluzioni. In questa guida verrà approfondita la funzione ‘include()’. Ne esistono altre che sono riportate nel manuale ufficiale. La sintassi di base è la seguente: 0 1 2 3 4 5 <? // inclusione di un file chiamato esterno.html include(’esterno.html’); ?> è preferibile utilizzare le stringhe con double quote perchè meglio gestite e più versatili: 0 1 2 3 4 5 <? // oppure con il double quote include("esterno.html"); ?> Le basi del linguaggio 2310 Come accennato in precedenza, il file da includere può trovarsi su una macchina diversa dalla nostra. Supponiamo che sia accessibile tramite il protocollo HTTP. La sintassi sarà: 0 1 2 3 4 5 6 7 8 <? /* inclusione di un file remoto. Su una macchina diversa, tramite il protocollo HTTP */ include("http://www.url_altro_sito.com/esterno.html"); ?> Questo modo di operare è del tutto corretto. Tuttavia va tenuto conto dei seguenti fattori: • l’elevato tempo di accesso al servente remoto, che può causare un ritardo nella generazione della pagina e può rallentare notevolmente la visualizzazione della stessa; • l’elaboratore servente potrebbe essere irraggiungibile o il file essere inesistente; • il contenuto del file remoto potrebbe essere modificato a nostra insaputa. Alcuni di questi ostacoli possono essere aggirati, altri no. Ad esempio, il primo problema non è risolvibile. Per quanto una connessione sia veloce ed i servizi performanti si aggiunge sempre un intervallo di tempo dovuto alla procedura di richiesta del file. Questo è un parametro molto importante, che va tenuto presente quando si effettua una scelta di questo tipo. Il tempo necessario, inoltre, non è sempre lo stesso ma dipende da svariati fattori, ad esempio il traffico sul sito remoto, il traffico sulla rete, ecc... Il secondo punto può essere affrontato in vari modi, quello più sbrigativo è sicuramente la gestione dell’errore generato con la mancata inclusione del file. Ecco un modo di procedere: 0 1 2 3 4 5 6 7 8 9 <? /* inclusione di un file remoto. Su una macchina diversa, tramite il protocollo HTTP. Compresa la gestione dell’errore!!! */ if( !@include("http://www.url_altro_sito.com/esterno.html") ) echo "<br><br> Problemi di visualizzazione! torna a trovarci..."; ?> In questo modo si è reso invisibile l’eventuale messaggio di errore dell’interprete tramite il prefisso ‘@’. Per il resto si tratta di un semplice ‘if’ che verifica il valore restituito dalla funzione ‘include()’, se il valore è falso visualizza il messaggio di errore, altrimenti include il file e prosegue. Se il file remoto è uno script, ad esempio PHP, prima di essere incluso viene interpretato dal servente, quindi viene incluso il risultato dello script generato in remoto e non sull’elaboratore su cui è ospitato il nostro script . Programmare in PHP --- Copyright © 2001-2002 Gianluca Giusti -- brdp @ urcanet.it Capitolo 216 Passaggio di variabili tramite l’HTTP Fino ad ora sono stati trattati i casi di singole pagine PHP in cui le variabili sono valorizzate, manipolate e visualizzate con l’interpretazione del singolo file. In questo modo l’utente che naviga la pagina non è in grado di interagire con gli script, non può passare dei dati al programma perchè non può editarne il codice. Il protocollo HTTP permette, tramite i marcatori HTML di passare dei dati tra le pagine, il PHP è in grado di ricevere ed elaborare queste informazioni. Nelle pagine seguenti verranno trattati i metodi di scambio di variabili dando per scontata la conoscenza, come detto in principio, dell’HTML. L’HTML permette al navigatore di inserire dati tramite il marcatore ‘form’ che riceve dagli attributi ‘action’ e ‘method’ le direttive relative al file che deve ricevere i dati e al modo in cui essi devono esseregli passati. L’attributo ‘method’ ammette due possibili valori: ‘get’ e ‘post’. Di seguito saranno approfondite le differenze tra i due metodi. 216.1 Metodo get Quando si sceglie il metodo ‘get’ le variabili ed il relativo valore vengono fornite allo script destinatario tramite la barra dell’indirizzo del browser. Il modo migliore per chiarire il concetto è l’utilizzo di un esempio. Verranno realizzati due script, ‘get_1.html’ e ‘get_2.php’. ‘get_1.html’ invierà i dati contenuti nel ‘form’ a ‘get_2.php’ utilizzando il metodo ‘get’, ‘get_2.php’ riceverà i dati, li manipolerà e li visualizzerà in una semplice pagina di saluto. Questo l’indirizzo dell’esempio: <http://www.urcanet.it/brdp/php_manual/ esempi/cap_3/get_1.html> Ecco il codice del file ‘get_1.html’: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <html> <head> <title> Passaggio del nome! </title> </head> <body> <br> Una semplice pagina HTML che passa nome e cognome ad uno script PHP che saluterà il navigatore. <br><br> <form method="get" action="get_2.php"> Dimmi il tuo nome: <input type="Text" name="nome"> <br><br> Ed ora il Cognome: <input type="Text" name="cognome"> <br><br> <input type="Submit" value="Adesso invia i dati in GET >>"> </form> </body> </html> Il primo file invia i due campi di testo al file destinatario ‘get_2.php’ che riceve due variabili valorizzate con i dati inseriti dal navigatore. Le variabili hanno il nome del campo del ‘form’, nell’esempio le variabili sono ‘$nome’ e ‘$cognome’ e sono di tipo stringa. Il codice del secondo script è molto semplice, non fa altro che visualizzare i valori delle due variabili. 2311 Passaggio di variabili tramite l’HTTP 2312 0 1 2 3 4 5 6 7 8 9 10 11 12 13 <html> <head> <title> Pagina di destinazione... </title> </head> <body> Ciao, <br><br> Il tuo nome è: <?=$nome?> <br> e il tuo cognome è: <?=$cognome?> </body> </html> Figura 216.1. Come appare il ‘form’ di invio dei dati. Figura 216.2. Nella barra degli indirizzi è evidenziata la sintassi del metodo ‘get’ per il passaggio delle variabili. L’obiettivo di questo esempio è quello di capire come funziona il metodo ‘get’, per farlo basta leggere il contenuto della barra degli indirizzi nel browser durante la visualizzazione dello script destinatario. L’indirizzo è simile a: http://www.urcanet.it/ ... ual/esempi/cap_3/get_2.php?nome=Gianluca&cognome=Giusti Risulta semplice e intuitivo capire come vengono passate variabili e valori. All’indirizzo della pagina viene aggiunto un carattere ‘?’ e di seguito tutte le coppie di variabili e rispettivo valore separate dal ‘=’, ad esempio: ‘nome=Gianluca’. Le coppie sono poi separate dal carattere ‘&’. Passaggio di variabili tramite l’HTTP 2313 216.2 Metodo post Nel metodo ‘post’ i dati non vengono visualizzati in nessun modo, essi sono spediti tramite il protocollo HTTP e non sono visibili sul navigatore. Una semplice verifica può essere eseguita modificando lo script ‘get_1.html’ nel seguente modo: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <html> <head> <title> Passaggio del nome! </title> </head> <body> <br> Una semplice pagina HTML che passa nome e cognome ad uno script PHP che saluterà il navigatore. <br><br> <form method="post" action="get_2.php"> Dimmi il tuo nome: <input type="Text" name="nome"> <br><br> Ed ora il Cognome: <input type="Text" name="cognome"> <br><br> <input type="Submit" value="Adesso invia i dati in GET >>"> </form> </body> </html> Salvato come ‘post_1.html’ è possibile testarne il funzionamento e verificare che nella pagina ‘get_2.php’ la barra degli indirizzi del programma di navigazione è priva delle coppie di variabili, allo stesso tempo lo script ha funzionato e viene visualizzato il messaggio di saluto correttamente. Analizzando lo script ‘post_1.html’ si nota che l’unica modifica è quella all’attributo ‘method’ del marcatore ‘form’. 216.3 Quale metodo scegliere? Non c’è una regola particolare per scegliere l’uno piuttosto che l’altro metodo. Possiamo dire che se la quantità di dati da inviare è grande è preferibile utilizzare il ‘post’. Il protocollo HTTP permette, tramite i form HTML, l’upload di file dall’elaboratore cliente a quello servente, in questi casi è bene utilizzare il metodo ‘post’. Nel file di configurazione del PHP (‘php.ini’) può essere definita sia la dimensione massima dei file che il servente accetterà tramite HTTP, sia la dimensione massima dei dati accettati tramite ‘post’. Quest’ultimo valore può essere definito valorizzando la variabile ‘post_max_size’ nel ‘php.ini’. Quando i dati da scambiare sono pochi e non importa che risultino direttamente visibili si può utilizzare il metodo ‘get’, che è comodo anche per quelle situazioni in cui si utilizza spesso il tasto avanti e indietro del navigatore. Le variabili sono memorizzate insieme all’indirizzo e quindi ogni volta che si richiama una pagina ad essa vengono rifornite le variabili e i loro valori. Per rendersi conto di questo basta tenere d’occhio la barra degli indirizzi durante le ricerche su un qualunque motore di ricerca, il 99% di essi passano i dati tramite il metodo ‘get’. È altrettanto vero che i dati passati al motore per le ricerche sono decisamente pochi, di solito si tratta di una stringa con dei parametri che il motore aggiunge automaticamente. Passaggio di variabili tramite l’HTTP 2314 216.4 Cosa è cambiato nel PHP versione 4.2 Dalle versioni del PHP 4.2 e successive la gestione delle variabili passate tramite moduli HTML è sensibilmente cambiata. Nel file di configurazione viene valorizzata a vero la variabile track_vars , in questo modo tutte le variabili presenti in un modulo ed inviate ad uno script PHP vengono inserite in un array associativo contenente il nome delle variabile e il relativo valore. Ad esempio nel caso dello script ‘get_2.php’ visto nelle sezioni 216.1 e 216.2 si avrebbe la necessità di distinguere il metodo di invio. Più precisamente nel caso di un invio tramite metodo ‘get’ il file ‘get_2.php’ dovrebbe essere così modificato: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 <html> <head> <title> Pagina di destinazione... </title> </head> <body> Ciao, <br><br> Il tuo nome è: <?=$HTTP_GET_VARS["nome"]?> <br> e il tuo cognome è: <?=$HTTP_GET_VARS["cognome"]?> </body> </html> Le differenze sono lampanti e riguardano le righe 9 e 10. L’interprete prende il valore ricevuto dalla variabile predefinita $HTTP_GET_VARS che come detto in precedenza è un array associativo Nel caso di un invio tramite metodo ‘post’ il programma andrebbe così modificato: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 <html> <head> <title> Pagina di destinazione... </title> </head> <body> Ciao, <br><br> Il tuo nome è: <?=$HTTP_POST_VARS["nome"]?> <br> e il tuo cognome è: <?=$HTTP_POST_VARS["cognome"]?> </body> </html> Questo tipo di gestione delle variabili può sembrare prolissa ma evita confusioni all’interprete e costringe il programmatore a specificare la variabile su cui operare. Ovviamente se si hanno pagine sviluppate secondo le vecchie specifiche basterà settare a falso la variabile track_vars nel file di configurazione del PHP, in questo modo tutto dovrebbe funzionare correttamente. Programmare in PHP --- Copyright © 2001-2002 Gianluca Giusti -- brdp @ urcanet.it Capitolo 217 L’utilizzo delle funzioni in PHP Una funzione può essere intesa come un "sotto-programma" a cui si possono fornire dei valori per ottenere una risposta da essi dipendente o meno. Il PHP mette a disposizione degli sviluppatori una vasta gamma di funzioni predefinite, tuttavia in alcune situazioni è necessario eseguire operazioni particolari, in questi casi è possibile definire delle funzioni personali che si comportano secondo le proprie necessità. Si prenda d’esempio lo script del paragrafo 215.3.5 in cui si visualizzava la data formattata in un modo particolare, è improponibile dover scrivere 38 righe di codice ogni volta che si desidera visualizzare la data all’interno di una pagina HTML in questo caso la soluzione migliore è realizzare una funzione dedicata che restituisce la data mediante una semplice "chiamata". Per evitare errori e ripetitive modifiche è consigliabile realizzare uno o più file in cui raccogliere le funzioni personali più utilizzate, una sorta di libreria, da premettere in ogni pagina tramite il costrutto ‘include()’. 217.1 Le funzioni predefinite Come detto in principio non è volontà dell’autore riportare l’elenco delle funzioni PHP, esse sono catalogate ed abbondantemente illustrate nel manuale ufficiale reperibile al sito internet: <http:// www.php.net>. Di seguito si vuole illustrare la struttura del manuale e il modo in cui esso va consultato per cercare, scegliere ed infine utilizzare le innumerevoli funzioni predefinite del linguaggio. Come sempre il modo migliore è l’utilizzo di un semplice esempio. Si supponga di voler realizzare uno programma che visualizzi una porzione di una stringa. Bisogna come prima cosa individuare le funzioni che permettono di manipolare le stringhe. Nella sezione "IV. Guida Funzioni" sono catalogate le funzioni messe a disposizione del programmatore, esse sono raggruppate per argomento. La sottosezione "LXXXIII. String functions" contiene le funzioni dedicate alla gestione delle stringhe. Come prima cosa si trova una descrizione della sezione e poi un lungo elenco, in ordine alfabetico, di funzioni con accanto una breve ma molto intuitiva descrizione. La funzione ‘substr()’ potrebbe risolvere il problema sollevato nell’esempio. Nel primo blocco della pagina descrittiva si trova il nome della funzione subito seguito dalle versioni dell’interprete PHP che la gestiscono e da una breve descrizione. Nel caso particolare: substr (PHP 3, PHP 4 >= 4.0.0) substr -- Return part of a string A seguire la descrizione approfondita che inizia con una delle parti più importanti della documentazione, infatti, in una sola riga viene spiegato l’intero funzionamento del comando. Nell’esempio proposto: string substr (string string, int start [, int length]) Come detto questa è forse la parte più importante, la prima parola descrive il tipo di dato restituito dalla funzione, nel caso particolare ‘string’, dunque la funzione restituisce una stringa. Dopo il nome della funzione tra parentesi i valori che la funzione può accettare ed il relativo tipo di dato, va sottolineato che tra parentesi quadre vengono elencati i parametri non obbligatori e il relativo tipo di dato. 2315 L’utilizzo delle funzioni in PHP 2316 Nel particolare la funzione accetta un primo dato di tipo stringa, separato da virgola il numero del carattere di partenza di tipo intero (si parte sempre da 0 e non da 1) ed infine come dato opzionale la lunghezza, di tipo intero, della porzione di stringa da estrarre. A questo schema seguono una descrizione approfondita ed una serie di esempi di funzionamento. Gli esempi se presenti sono molto utili ed autoesplicativi, inoltre trattano varie eccezioni ed eventuali casi particolari. In fine ma non meno importante la sezione contenente le funzioni correlate o in qualche modo relazionate con quella in oggetto. Il manuale spesso suggerisce di consultare anche altre funzioni, in questo caso: See also strrchr() and ereg(). Spesso non esiste un unico modo per raggiungere la soluzione del problema e spesso questa ultima sezione fornisce degli spunti molto interessanti che possono portare ad una soluzione più semplice e brillante, il consiglio è di non sottovalutarla. A questo punto è doveroso trattare almeno un esempio di utilizzo della funzione scelta come campione. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <? // La stringa iniziale va in $var $var = "Questa è la stringa di partenza"; // 0123456789012345678901234567890 // 1234567890 // Le due righe superiori semplificano il conteggio dei caratteri. // Questo esempio prende la parte: "la stringa" $sub = substr($var, 9, 10); echo $sub; // Per selezionare gli ultimi 2 caratteri basta usare: $sub = substr($var, -2); echo "<br><br> ".$sub; // Per selezionare i primi 2 caratteri basta usare: $sub = substr($var, 0, 2); echo "<br><br> ".$sub; // Se non specifico la lunghezza della porzione continua fino alla fine $sub = substr($var, 5); echo "<br><br> ".$sub; ?> Il risultato di questo semplice script è simile a: la stringa za Qu a è la stringa di partenza Anche questo esempio è raggiungibile all’indirizzo: <http://www.urcanet.it/brdp/php_manual/esempi/ cap_4/substr.php> L’utilizzo delle funzioni in PHP 2317 217.2 Le funzioni definite dall’utente Un modo molto semplice di schematizzare il concetto di funzione è pensare ad una scatola che permette tramite due fori di inserire ed estrarre dei valori. All’interno della scatola può essere utilizzato qualunque costrutto messo a disposizione dal linguaggio, ecco perchè si parla di "sottoprogrammi". Lo schema di figura 217.1 può essere di aiuto. Figura 217.1. Il blocco di programma principale contiene due scatole (funzioni) che ricevono due valori e restituiscono in un caso la somma, in un altro la differenza. L’esempio classico è quello di una semplice funzione di saluto: 0 <? 1 //---------------- Definizione delle funzioni 2 3 function saluto($ora){ 4 5 /* 6 Questa funzione genera un messaggio di saluto 7 in base al valore della variabile $ora passatagli 8 che contiene l’ora, con valore tra 0 e 24 9 */ 10 11 if (5 < $ora && $ora <= 12){ 12 echo "Buon Giorno."; 13 }elseif(12<$ora && $ora <= 18){ 14 echo "Buon Pomeriggio."; 15 }elseif(18<$ora && $ora <= 24){ 16 echo "Buona Sera!"; 17 }else{ 18 echo "Guarda che razza di ora è! Ma quando dormi?!"; 19 } 20 } 21 22 23 //---------------- Programma principale 24 25 $orario = date("H"); // estraggo l’ora attuale 26 27 // Richiamo la funzione e ci aggiungo del testo... 28 29 saluto($orario); 30 echo " Come va oggi?!?"; L’utilizzo delle funzioni in PHP 2318 31 32 // non serve riscrivere il codice posso inserire 33 // il saluto con una sola RIGA di codice!!! 34 35 echo "<br><br> Ancora un saluto: "; saluto($orario); 36 ?> Lo script è costituito da una parte contenente le dichiarazioni delle varie funzioni, nel caso specifico una sola, e dal programma principale che le richiama una o più volte. Come prima cosa è importante eseminare la sintassi per la dichiarazione delle funzioni. function nome_funzione(variabile_1, variabile_2, .... , variabile_n){ istruzioni funzione return valore se necessario } Il costrutto ‘function’ segna l’inizio della dichiarazine, subito dopo va assegnato un nome che deve essere unico nel programma, non possono esserci più funzioni aventi lo stesso nome, tra parentesi tonde è possibile elencare le variabili, se esistono, che devono essere fornite alla funzione, se sono più di una vanno separate da una virgola (‘,’). Il corpo della funzione è, infine, contenuto tra parentesi graffe (‘{...}’). Una volta dichiarata, la funzione, può essere richiamata tutte le volte che si vuole, è questo il vantaggio che si ha nel suddividere il lavoro in piccoli problemi e a risolverli con piccoli e semplici sotto-programmi da richiamare ogni volta che se ne ha bisogno. Come detto la funzione può restituire dei valori, dunque quando richiamata può essere vista come una variabile contenente dei valori. Se si modifica l’esempio precedente come riportato di seguito, la funzione non scriverà nulla sullo schermo ma valorizzerà tramite il comando ‘return’ il nome della funzione, esso potrà essere visualizzato, assegnato ad un’altra variabile, ecc... Proprio come fosse una variabile. 0 <? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 //---------------- Definizione delle funzioni function saluto($ora){ /* Questa funzione genera un messaggio di saluto in base al valore della variabile ricevuta $ora che contiene l’ora con valore tra 0 e 24 e lo restituisce al programma principale tramite l’istruzione "return" */ if (5 < $ora && $ora <= 12){ return "Buon Giorno."; }elseif(12<$ora && $ora <= 18){ return "Buon Pomeriggio."; }elseif(18<$ora && $ora <= 24){ return "Buona Sera!"; }else{ return "Guarda che razza di ora è! Ma quando dormi?!"; } } //---------------- Programma principale $orario = date("H"); // Richiamo la funzione e ci aggiungo del testo... L’utilizzo delle funzioni in PHP 2319 29 30 $msg = saluto($orario); // assegno il valore della funzione 31 echo $msg." Come va oggi?!?"; 32 33 // una sola RIGA di codice CONCATENATO come fosse una variabile 34 35 echo "<br><br> Ancora un saluto: ".saluto($orario); 36 37 ?> Le modifiche adottate nelle righe 14, 16, 18, 20 provvedono tramite il comando ‘return’ ad assegnare un valore al nome della funzione invece di visualizzarlo sullo schermo. Di conseguenza cambia il modo di manipolare la funzione al momento della chiamata, infatti, in questo modo ritorna un valore che può essere trattato come una semplice variabile. Nella riga 30 viene assegnato il valore restituito dalla funzione ad un’altra variabile, mentre nella riga 35 viene concatenato in una stringa. A questo punto si potrebbe avere la necessità di scegliere se far visualizzare il messaggio direttamente dalla funzione o farlo ritornare come valore. Complicando leggermente l’esempio si può risolvere il problema. Una semplice soluzione è quella di passare una seconda variabile, che a seconda del suo stato (vero o falso) fa comportare la funzione in due modi diversi. 0 <? 1 //---------------- Definizione delle funzioni 2 3 function saluto($ora, $modo){ 4 5 /* 6 Questa funzione genera un messaggio di saluto 7 in base al valore della variabile ricevuta $ora 8 che contiene l’ora con valore tra 0 e 24 9 e lo restituisce al programma principale tramite 10 l’istruzione "return" se $modo è falso, se è vero 11 ne visualizza il valore. 12 */ 13 14 if (5 < $ora && $ora <= 12){ 15 $msg = "Buon Giorno."; 16 }elseif(12<$ora && $ora <= 18){ 17 $msg = "Buon Pomeriggio."; 18 }elseif(18<$ora && $ora <= 24){ 19 $msg = "Buona Sera!"; 20 }else{ 21 $msg = "Guarda che razza di ora è! Ma quando dormi?!"; 22 } 23 24 // controllo sul flag $modo. 25 if($modo){ 26 echo $msg; 27 }else{ 28 return $msg; 29 } 30 31 } 32 33 //---------------- Programma principale 34 35 $orario = date("H"); 36 $modo = false; 37 38 // Richiamo la funzione e ci aggiungo del testo... 39 $msg = saluto($orario, $modo); 40 echo $msg." Come va oggi?!?"."<br><br>"; 41 42 // Adesso posso anche farlo scrivere direttamente, ecco come: 2320 L’utilizzo delle funzioni in PHP 43 saluto($orario,1); 44 ?> Adesso la funzione si aspetta due parametri, il primo serve a generare il messaggio di saluto, il secondo (righe 25-29) a determinare il comportamento della funzione. Se cambia la dichiarazione deve cambiare anche la chiamata alla funzione, infatti, nelle righe 39 e 43 vengono passati i due parametri e la funzione si comporta di conseguenza. Quando si richiama una funzione non importa il nome delle variabili che gli vengono fornite, quello che importa è l’ordine con cui esse vengono elencate. Dunque i valori passati alla funzione andranno nelle variabili locali (della funzione) definite al momento della dichiarazione della stessa. Nell’esempio seguente viene approfondito questo aspetto tramite una funzione che genera e visualizza una scheda informativa di un potenziale utente. 0 <? 1 //---------------- Definizione delle funzioni 2 3 function scheda($nome, $cognome){ 4 5 /* 6 Questa funzione ha lo scopo di chiarire il concetto di 7 variabile locale e globale. Fare inoltre attenzione 8 all’ordine con cui sono passate le variabili 9 */ 10 11 global $tel; 12 13 echo "<br>Scheda informativa utente: <br><br> "; 14 echo "<br>Nome: ".$nome; 15 echo "<br>Cognome: ".$cognome; 16 echo "<br>Telefono: ".$tel; 17 echo "<br>e-mail: ".$email; 18 echo "<br><br>-----------------------<br>"; 19 } 20 21 //---------------- Programma principale 22 23 $nome = "Gianluca"; 24 $cognome = "Giusti"; 25 $tel = "06/66666666"; 26 $email = "brdp @ urcanet.it"; 27 28 // richiamo la funzione che genera la scheda. 29 scheda($nome, $cognome); 30 31 // il nome delle variabili non importa! Importa invece l’ordine 32 // con cui vengono passate alla funzione! Ecco la prova: 33 scheda($cognome, $nome); 34 ?> Come detto in principio, le funzioni sono dei piccoli programmi a se stanti, dunque le variabili utilizzate al loro interno, dette "variabili locali", non hanno lo stesso valore di quelle utilizzate nel programma principale, dette "variabili globali" anche se nominate allo stesso modo. Si può dire che sono variabili diverse. Un modo per far coincidere le variabili locali e globali è passare le variabili globali come argomento della funzione, proprio come fatto negli esempi precedenti. Un secondo metodo, è l’utilizzo del comando ‘global’. Nella riga 11 dell’esempio precedente viene utilizzato per "catturare" il valore della variabile globale $tel all’interno della funzione. Il risultato dell’ultimo programma è simile a: L’utilizzo delle funzioni in PHP 2321 Scheda informativa utente: Nome: Gianluca Cognome: Giusti Telefono: 06/66666666 e-mail: ----------------------Scheda informativa utente: Nome: Giusti Cognome: Gianluca Telefono: 06/66666666 e-mail: ----------------------- Come prima cosa va notata l’assenza dell’indirizzo e-mail, questo dipende dal fatto che la variabile $email non è stata fornita in alcun modo alla funzione quindi al suo interno non è valorizzata. Al contrario le altre variabili sono valorizzate, $nome e $cognome vengono passate al momento della chiamata mentre la variabile $tel viene associata a quella globale. L’utilizzo di ‘global’ non è consigliabile dal momento che ogni modifica alla variabile utilizzata come globale all’interno della funzione si riperquote anche nel programma principale. Se non si hanno motivi particolari non ha senso utilizzare questo metodo. Un ottimo esercizio per l’utente è la verifica di quanto appena detto. Modificare l’ultimo esempio al fine di dimostrare che le modifiche alla variabile $tel effettuate all’interno della funzione si riperquotono anche nel programma principale, mentre eventuali modifiche alle variabili passate come argomento all’interno della funzione non hanno effetto nel programma principale. Per i più esperti la situazione è simile al passaggio di variabili per "valore" o per "riferimento". La funzione, inoltre, viene richiamata due volte invertendo l’ordine dei parametri a dimostrazione che il nome delle variabili non ha alcun importanza ma quello che importa è l’ordine con cui vengono dichiarate e passate al momento della chiamata. In conclusione il modo migliore e più elegante per realizzare la scheda utente dell’esempio è fornire tutti i dati necessari alla funzione come parametri della chiamata. 0 <? 1 //---------------- Definizione delle funzioni 2 3 function scheda($nome, $cognome, $tel, $email){ 4 5 // Il modo più corretto è il passaggio delle variabili 6 // Salvo casi particolari in cui si è obbligati ad usare il global 7 8 echo "<br>Scheda informativa utente: <br><br> "; 9 echo "<br>Nome: ".$nome; 10 echo "<br>Cognome: ".$cognome; 11 echo "<br>Telefono: ".$tel; 12 echo "<br>e-mail: ".$email; 13 echo "<br><br>-----------------------<br>"; 14 } 15 16 17 //---------------- Programma principale 18 19 $nome = "Gianluca"; 20 $cognome = "Giusti"; 21 $telefono = "06/66666666"; 22 $posta_elettronica = "brdp @ urcanet.it"; 2322 L’utilizzo delle funzioni in PHP 23 24 // richiamo la funzione che genera la scheda. I nomi non contano! 25 scheda($nome, $cognome, $telefono, $posta_elettronica); 26 27 ?> Uno degli aspetti più importanti di un sito Internet è l’estetica ed è anche la parte che viene rinnovata più di frequente. Si pensi alla necessità di elencare degli oggetti secondo particolari vesti grafiche, utilizzando una funzione è possibile modificare varie pagine, in cui essa viene richiamata, modificando una sola porzione di codice. Un altro esempio è dato dai siti in cui è possibile personalizzare la formattazione dei dati tramite la scelta di modelli predefiniti, in questo caso la funzione potrebbe ricevere un parametro in più che rappresente il modello, oppure si potrebbero implementare varie funzioni che formattano i medesimi dati in modo differente. Come conclusione si può senza dubbio affermare che un programma strutturato è molto più leggibile ed elegante di uno costituito da un unico blocco di codice spesso incomprensibile. In fine va notato che ci sono delle operazioni che vengono ripetute spesso nel lavoro di tutti i giorni, ad esempio formattazione della data in vari formati, connessione e interrogazioni di basi di dati, paginazione di elenchi, gestione di immagini, upload di file, ecc... La cosa più intelligente è creare dei file, paragonabili a librerie, contenenti le dichiarazioni delle funzioni più utilizzate, a questo punto basterà includere tali "librerie" in cima agli script in modo da poter richiamare le funzioni senza dovrele dichiarare ogni volta. Ancora più corretto è la creazione di "librerie" contenenti delle classi con cui poter dichiarare dei veri e propri oggetti ma questo verrà spiegato nella sezione dedicata alla programmazione avanzata. Un esercizio interessante lasciato al lettore è quello di implementare una funzione chiamata ‘isint($var)’, supponendo che non esista la funzione già vista ‘is_integer()’, che utilizzando ‘gettype()’ restituisca un valore vero se la variabile passata è un intero o falso se la variabile è di un altro tipo. 217.3 Le funzioni ricorsive Il PHP permette di richiamare le funzioni in modo ricorsivo, ovvero è possibile richiamare una funzione dal suo interno. Un classico esempio applicativo di questa tecnica è il calcolo del fattoriale. Come noto il fattoriale di un numero intero positivo n (indicato come n! ) è pari a n*(n-1)*(n-2)*...*(n-(n-1)) . Ad esempio: 5! = 5*4*3*2*1 = 120 Ecco come risolvere il problema con l’utilizzo di una funzione ricorsiva: 0<html><body> 1 <? 2 //---------------- Definizione delle funzioni 3 4 function fattoriale($numero){ 5 6 if($numero <= 1){ 7 return 1; // abbandona la ricorsione 8 }else{ 9 return $numero*fattoriale($numero-1); //la funzione richiama se stessa 10 } 11 12 } 13 14 15 //---------------- Programma principale 16 17 echo "<br>Calcolo del fattoriale:<br>"; L’utilizzo delle funzioni in PHP 2323 18 19 for($i=-2; $i<=10; $i++){ 20 echo "<br>Il fattoriale di $i è: ".fattoriale($i); 21 } 22 23 ?> 24 25 </body></html> All’interno della dichiarazione, riga 9, viene richiamata la funzione stessa passandogli il numero decrementato di uno. Questo perchè n! = n*(n-1)! = n*(n-1)*(n-2)! e così via... Il fattoriale di 0 è pari ad 1 per definizione. Per semplificare il controllo si è stabilito che il fattoriale di un numero negativo è pari ad 1 anche se non è corretto matematicamente. L’attenzione non deve essere focalizzata sull’aspetto matematico ma sul fatto che la funzione nel programma principale viene richiamata una sola volta. Ancora più importante in problemi di questo genere è la definizione di una condizione di arresto, in questo caso quando il numero passato alla funzione è ‘<=1’ la funzione abbandona la ricorsione e restituisce valore pari ad 1. Se si sbaglia o si tralascia la condizione di uscita il programma potrebbe entrare in un ciclo infinito e non smetterebbe mai l’esecuzione. Programmare in PHP --- Copyright © 2001-2002 Gianluca Giusti -- brdp @ urcanet.it Capitolo 218 La gestione del file system Il file system è ben gestito dal PHP, le funzioni a disposizione degli sviluppatori sono innumerevoli, inoltre sono ben integrate con il sistema operativo in modo particolare GNU/Linux. Ad esempio è possibile ottenere e cambiare i permessi, il proprietario e il gruppo di un file, creare collegamenti simbolici, copiare, spostare, eliminare directory e file. Dunque gli strumenti a disposizione non mancano e molti di essi verranno trattati nelle pagine seguenti. Prima di entrare nello specifico è bene precisare ancora una volta che il file system su cui il PHP opera è quello dell’elaboratore servente, quindi se si crea un file esso viene creato sul disco del servente e non su quello del cliente. Tramite il protocollo HTTP il PHP può gestire anche il trasferimento di file dall’elaboratore cliente a quello servente, questo però verrà trattato nella sezione dedicata alla programmazione avanzata. 218.1 Concetto di file Un file può essere visto come un contenitore nel quale immagazzinare informazioni. La gestione fisica del file su disco viene effettuata dal sistema operativo a cui si interfaccia il PHP. Per poter accedere alle informazioni contenute in un file è necessario aprirlo, leggerne il contenuto, eventualmente modificarlo e infine chiuderlo. I dati vengono salvati nel file sotto forma di righe, per indicare il fine riga nei file di testo viene utilizzato ‘\n’, mentre la fine del file è ottenuta tramite la funzione ‘feof()’ che restituisce un valore booleano vero se ci si trova alla fine del file. La particolarità fondamentale di questa struttura è il suo accesso, a differenza degli array non è possibile puntare direttamente ad una riga ben precisa del file è dunque necessario scorrere il suo contenuto fino ad arrivare alla riga desiderata. Questo tipo di accesso viene detto "accesso sequenziale". Non ci sono, inoltre, limiti massimi o minimi per le dimensioni del file, esse dipendono dalla disponibilità di spazio su disco. 218.2 Apertura di un file Se un file è un contenitore per poter accedere al suo contenuto è necessario aprirlo, per farlo si utilizza la funzione ‘fopen()’ a cui va fornito il file con il percorso, se diverso da quello dello script, e il tipo di apertura. Dunque al momento dell’apertura del file bisogna dichiarare il tipo di operazione che si desidera eseguire su di esso, ad esempio se si vuole solo leggere, scrivere o semplicemente aggiungere dati alla fine. Ecco l’elenco dei possibili modi di accedere ad un file in PHP: • ‘’r’’ Apre in sola lettura; posiziona il suo puntatore all’inizio del file; • ‘’r+’’ Apre in lettura e scrittura; posiziona il suo puntatore all’inizio del file; • ‘’w’’ Apre in sola scrittura; posiziona il suo puntatore all’inizio del file e ne elimina il contenuto. Se il file non esiste lo crea; • ‘’w+’’ Apre in lettura e scrittura; posiziona il suo puntatore all’inizio del file e ne elimina il contenuto. Se il file non esiste lo crea; 2324 La gestione del file system 2325 • ‘’a’’ Apre in sola scrittura; posiziona il suo puntatore alla fine del file. Se il file non esiste lo crea; • ‘’a+’’ Apre in lettura e scrittura; posiziona il suo puntatore alla fine del file. Se il file non esiste lo crea; Il PHP permette anche di aprire file remoti tramite i protocolli più diffusi come HTTP e FTP, ovviamente il file deve essere raggiungibile almeno in lettura. Ecco qualche esempio di apertura di file: 0 1 2 3 $f $f $f $f = = = = fopen fopen fopen fopen ("dati.txt", "w"); ("/home/qualche_percorso/dati.txt", "a"); ("http://www.php.net/", "r"); ("ftp://nome_utente:password@indirizzo_del_sito_ftp.com/", "w"); Va notato che la funzione ritorna un intero. La variabile ‘$f’ contiene i riferimenti al file aperto, viene anche detto "puntatore al file" anche se non ha nulla a che vedere con la "struttura puntatore". Tutte le operazione sarnno eseguite sul puntatore al file. Nella riga 0 il file viene aperto in sola scrittura un file che si trova nella stessa directory dello script, se non esistere viene creato. Nella riga 1 il file viene aperto in un ben preciso punto del del disco del servente. Negli ultimi due esempi i file aperti risiedono in remoto e sono aperti tramite i due protocolli HTTP ed FTP Fare molta attenzione ai permessi dei file che si intende manipolare e delle directory in cui sono contenuti. Ricordare che l’utente che accede al file è quello che lancia il servente HTTP e di conseguenza l’interprete PHP in esso caricato come modulo. Tale utente viene specificato nel file di configurazione del servente. 218.3 Lettura di un file di testo Il primo passo sarà quello di leggere un semplice file di testo esistente e contenuto nella stessa directory dello script. Verrà utilizzato il metodo di sola lettura con l’indispensabile controllo di errore e ancora prima di esistenza del file da leggere. Se si salvano informazioni riservate in file di testo è bene farlo in una directory che non faccia parte dei documenti WEB altrimenti potrebbe essere richiamato e letto direttamente dal navigatore. Inoltre è importante nascondere eventuali errori mediante una corretta gestione degli stessi al fine di evitare la visualizzazione di informazioni importanti come il percorso e il nome del file che si tenta di aprire. Prima di scrivere il codice è bene creare il file da leggere, nominarlo come ‘dati_1.txt’ e riempirlo con del semplice testo. Un esempio di dati_1.txt: Salve a tutti, scrivo nel file per poi leggere con php. di seguito una riga vuota e poi il file finisce! Ecco il programma che legge il file appena creato: 0 1 2 3 4 5 <html><body> <? if (file_exists("dati_1.txt")){ echo "Il file dati_1.txt esiste. Ecco il suo contenuto:<br>"; La gestione del file system 2326 6 7 8 9 10 11 12 13 14 16 17 18 19 20 21 22 23 $f = @fopen("dati_1.txt", "r"); // apre il file in sola lettura if($f){ while(!feof($f)){ // un semplice while fino alla fine del file $riga = fgets($f,4096); // legge la riga echo "<br>".$riga; // visualizza la riga } @fclose($f); // è importante chiudere il file }else{ echo "Errore durante l’apertura del file!"; } }else{ echo "Il file dati_1.txt NON esiste!"; } ?> </body></html> Nella riga 3 viene controllata l’esistenza del file di testo tramite la funzione ‘file_exists()’ che come riportato nel manuale ufficiale alla sezione "XXVI. Filesystem functions" ritorna un valore booleano vero se il file esiste falso negli altri casi. Questa sezione del manuale è ricca di funzioni per la gestione dei file si consiglia vivamente di approfondirne la lettura. Alla riga 6 il file viene aperto in sola lettura è bene fare attenzione alla gestione dell’errore. Se l’apertura va a buon fine tramite una struttura ciclica ne viene visualizzato il contenuto. La lettura viene interrotta nel momento in cui la funzione ‘feof()’ resituisce valore vero, questo accade quando si arriva alla fine del file. Per la lettura delle singole righe del file è stata utilizzata la funzione ‘fgets()’ che restituisce una stringa o un valore falso in caso di errore. Molto importante è l’istruzione della riga 12 con la quale viene chiuso il puntatore al file definito nella fase di apertura. È bene liberare un file prima possibile per evitare problemi di scrittura concorrenziale. Anche questa funzione ritorna un valore booleano vero se l’operazione va a buon fine, falso altrimenti. Se il file di testo da leggere è piccolo si può utilizzare la funzione ‘file("nome_del_file ")’, ovviamente oltre al nome del file può essere specificato un particolare percorso e il tutto può essere contenuto in una variabile da passare come parametro. La funzione ‘file()’ resituisce un array formato da tanti elementi quante sono le righe del file di testo, ogni elemento conterrà il testo della riga relativa. Ad esempio nel caso del precedente file ‘dati_1.txt’: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <html><body> <? $appo = @file("dati_1.txt"); if ($appo){ echo "Operazione riuscita il contenuto del file dati_1.txt è nell’array <b>\$appo</b><br>"; $i=0; foreach($appo as $valore) // visualizzo il contenuto dell’array echo "<br>".$valore; }else{ echo "Errore nella lettura del file! Accertarsi che esista e che i permessi siano corretti"; } ?> </body></html> Questa funzione risulta molto comoda e rapida inquanto non necessita di istruzioni per l’apertura La gestione del file system 2327 e la chiusura del file. È evidente che in questo modo il contenuto può essere soltanto letto e non modificato. In caso di file di dimensioni medio grandi è preferibile utilizzare le funzioni classiche viste in precedenza che benchè più macchinose garantiscono una migliore gestione del file e della memoria. 218.4 Scrittura in un file di testo Come al solito prima di poter operare sul contenuto del file bisogna aprirlo, ovviamente per poter inserire dei dati nel contenitore bisogna aprirlo in modalità di scrittura. Come visto in precedenza esistono varie modalità e per ogni situazione va scelta quella ottimale. Di seguito esamineremo alcuni metodi di scrittura nel file. Il tipo ‘r+’ permette di leggere e scrivere nel file che si sta aprendo e posiziona il puntatore all’inizio del contenitore senza alterarne a priori il contenuto. È utile quando bisogna posizionare una riga in una ben precisa posizione del file. Nel caso di ‘w’ e ‘w+’ il file viene aperto in scrittura o scrittura e lettura e viene immediatamente svuotato. Può essere comodo nel caso di file di appoggio che possono essere sovrascritti senza doverne controllare il contenuto. Il metodo di apertura ‘a’ e ‘a+’, che serve ad accodare righe al file, verrà trattato in dettaglio nel paragrafo 218.5. Nell’esempio seguente si salva nel file ‘dati_3.txt’ l’indirizzo IP dell’ultimo visitatore che ha caricato la pagina ‘3.php’. Anche questo come tutti gli esempi di questo capitolo è raggiungibile al solito indirizzo: <http://www.urcanet.it/brdp/php_manual/esempi/> nel caso specifico: <http:// www.urcanet.it/brdp/php_manual/esempi/cap_5/3.php> 0 <html><body> 1 2 <? 3 $f = @fopen("dati_3.txt", "w"); // lo apre e lo svuota. se non esiste lo crea 4 if($f){ 5 echo "<br><br>file <a href=\"dati_3.txt\">dati_3.txt</a> Aperto correttamente."; 6 echo "<br><br>Sto salvando i tuoi dati nel file"; 7 8 $frase = "Ultimo visitatore ad aver eseguito lo script 3.php \n\n"; 9 $frase = $frase."il suo IP:".$REMOTE_ADDR." \n"; 10 11 @fputs($f,$frase); // scrive la frase nel file tramite $f 12 @fclose($f); // è importante chiudere il file 13 14 echo "...... Fatto!"; 15 16 }else{ 17 echo "<br>Errore durante l’apertura del file dati_3.txt"; 18 } 19 ?> 20 21 </body></html> Nella riga 3 il file viene aperto in sola scrittura e come più volte ripetuto il suo contenuto viene cancellato. Dunque questo codice sarà in grado di mantenere traccia soltanto dell’ultimo visitatore. Sarebbe più interessante memorizzare più visite ma bisogna fare i conti con la crescita del file, se la pagina è molto frequentata le dimensioni del file di log potrebbero crescere a dismisura fino a saturare lo spazio su disco. Un buon esercizio potrebbe essere la realizzazione di uno script che tenga traccia degli ultimi ‘$n’ visitatori, dove ‘$n’ è un parametro che può essere impostato a seconda delle esigenze. Di seguito una possibile soluzione: La gestione del file system 2328 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 <html><body> <? $n = 4; // numero di visite da mantenere $f = @fopen("dati_4.txt", "r"); if($f){ echo "<br>file dati_4.txt esistente ed aperto correttamente <br>"; $i=0; while( !feof($f) && $i<$n-1 ){ // finchè fine del file o il $i< $n-1 $righe[$i] = @fgets($f,4096); // file piccolo! utilizzo array sacmbio $i++; } @fclose($f); // è importante chiudere il file $f = @fopen("dati_4.txt", "w"); // adesso lo riempio con i nuovi dati. if($f){ echo "<br><br>file <a href=\"dati_4.txt\">dati_4.txt</a> Aperto correttamente. Sto salvando i tuoi dati"; $frase = "visitatore di 4.php - "; $frase = $frase."il suo IP:".$REMOTE_ADDR." alle ore: ".date("d-m-Y G:i:s")." \n"; @fputs($f,$frase); // scrive la frase nel file tramite $f for ($i=0; $i<count($righe); $i++) @fputs($f,$righe[$i]); @fclose($f); // è importante chiudere il file echo ".......Fatto!"; } }else{ echo "<br>Il file dati_4.txt non esiste. Lo creo."; $f = @fopen("dati_4.txt", "w"); if($f){ echo "<br><br>file <a href=\"dati_4.txt\">dati_4.txt</a> Aperto correttamente. Sto salvando i tuoi dati"; $frase = "visitatore di 4.php - "; $frase = $frase."il suo IP:".$REMOTE_ADDR." alle ore: ".date("d-m-Y G:i:s")." \n"; @fputs($f,$frase); @fclose($f); // scrive la frase nel file tramite $f // è importante chiudere il file echo ".......Fatto!"; }else{ echo "<br><br>Non posso creare il file dati_4.txt"; } } ?> </body></html> Ci sono vari modi per risolvere il problema, quello usato per questo esempio è volutamente prolisso al fine di utilizzare più volte le funzioni sotto esame così da rendere più semplice l’apprendimento. Concettualmente si è ragionato in questi termini: se il file esiste { - leggo le prime $n-1 righe del file - le salvo in un array di appoggio La gestione del file system - 2329 chiudo il file apro il file in scrittura cancellandone il contenuto salvo i dati relativi alla connessione attuale nel file salvo tutte le righe dell’array di appoggio chiudo il file } altrimenti { - apro il file in scrittura e viene creato - salvo i dati relativi alla connessione attuale nel file - chiudo il file } in realtà non viene fatto un controllo sull’esistenza del file ma si è considerato che se non si riesce ad aprire in sola lettura con il metodo ‘r’ il file o non esiste o non è leggibile. Nel ciclo di riga 9 vengono prese le prime ‘$n-1’ righe del file o tutto il file se ha meno di ‘$n’ righe, la condizione che per prima non viene soddisfatta fa abbandonare il ciclo. Nelle righe 21 e 43 è stata usata la variabile predefinita ‘$REMOTE_ADDR’ che contiene l’indirizzo IP del visitatore e di seguito la funzione ‘date()’ già incontrata nalla sezione 214.1 che in questo caso ritorna la data nella forma del tipo: ‘31-10-2002 15:13:13’. Maggiori informazioni in merito possono essere trovate nella sezione "XVI. Date and Time functions" del manuale ufficiale. In fine nella righa 24 al posto della solita struttura ‘foreach’ è stata utilizzata volutamente la funzione ‘count()’ che restituisce il numero di elementi dell’array che gli viene passato come parametro. In conclusione va notato che l’ultima visita verrà registrata in testa al file mentre le più vecchie verranno scartate mano a mano che ne entreranno delle nuove. Il risultato ottenuto nel file ‘dati_4.txt’ è simile a: visitatore visitatore visitatore visitatore di di di di 4.php 4.php 4.php 4.php - il il il il suo suo suo suo IP:192.168.1.153 IP:192.168.1.153 IP:192.168.1.153 IP:192.168.1.153 alle alle alle alle ore: ore: ore: ore: 31-10-2002 31-10-2002 31-10-2002 31-10-2002 15:13:24 15:13:17 15:13:12 15:10:21 Come conclusione viene proposto un esempio riepilogativo in merito al quale non verranno fornite spiegazioni, sarà compito del lettore capirne il comportamento. Per testarne il funzionamento è tuttavia possibile collegarsi all’indirizzo: <http://www.urcanet.it/brdp/php_manual/esempi/cap_5/5.php> 0 <html><body> 1 <? 2 /* 3 Primo tentativo di apertura del file inesistente dati_5.txt in sola lettura 4 il tentativo di apertura fallisce perchè la modalità ’r’ non 5 crea il file in caso di inesistenza, a differenza delle modalità 6 ’w’ e ’a’ che se non esiste lo creano. Quindi il controllo seguente 7 restituirà il messaggio di errore... 8 */ 9 10 $f = @fopen("dati_5.txt", "r"); 11 12 if($f){ 13 echo "<br>1) file dati_5.txt Aperto. Ecco il contenuto: <br>"; 14 //Se apre il file facciamo scrivere il contenuto 15 while(!feof($f)){ // finchè non raggiungo la fine del file 16 $riga = @fgets($f,4096); 17 echo "<br>".$riga; 18 } 19 @fclose($f); // è importante chiudere il file 20 }else{ 21 echo "<br>1) Apertura del file dati_5.txt FALLITA! Ora lo creo e lo riempio."; 22 } La gestione del file system 2330 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 /* Secondo tentativo apro in sola scrittura il file il tentativo di apertura riesce perchè la modalità ’w’ crea il file in caso di inesistenza. Il controllo seguente restituirà messaggio positivo. ATTENZIONE in questo caso il file viene svuotato al momento dell’apertura, il contenuto viene perso. */ if (!file_exists("dati_5.txt")){ $f = @fopen("dati_5.txt", "w"); if($f){ echo "<br><br>2) file dati_5.txt Aperto correttamente. Lo riempio"; // sappiamo che va a buon fine e quindi scriviamoci qualcosa dentro. // notare che \n inserisce un fine riga!!! $frase = "Ciao Popolo. \n"; $frase = $frase."Scrivo nel mio primo file in PHP \n"; $frase = $frase."Speriamo bene! \n"; $frase = $frase."CIAO"; @fputs($f,$frase); @fclose($f); // scrive la frase nel file tramite $f // è importante chiudere il file }else{ echo "<br><br>2) Apertura del file dati_5.txt <strong>FALLITA!</strong>"; } }else{ echo "<br><br>2) Il file dati_5.txt esiste già. Allora lo RIMUOVO!"; if(@unlink ("dati_5.txt")){ echo "<br><br> FILE dati_5.txt RIMOSSO CORRETTAMENTE"; }else{ echo "<br><br> ERRORE durante la rimozione di dati_5.txt"; } } ?> </body></html> In questo ultimo esempio viene utilizzata per la prima volta la funzione ‘unlink()’ che serve ad eliminare il file che riceve come parametro, essa restituisce un intero che assume valore pari a 0 o falso se l’operazione di cancellazione non va a buon fine. 218.5 Accodare testo in un file Ovviamente esistono metodi più semplici, immediati e dunque migliori per tenere traccia di qualunque evento. Prima di continuare è bene ricordare che il servente HTTP memorizza in file di log le informazioni relative alle connessioni quindi se non si hanno particolari esigenze tracciare le visite degli utenti potrebbe essere un’operazione ridondante. Il PHP come visto nella sezione 218.2 permette di aprire un file in modalità "append", ovvero in modo che le righe inserite vengano appese alla fine del file. questo metodo è utilizzabile passando alla funzione ‘fopen()’ il parametro ‘a’ o ‘a+’, nel primo caso il file viene aperto in sola scrittura mentre nel secondo in scrittura e lettura, il puntatore viene posizionato alla fine del file e se non esiste il file specificato viene creato. Se si pensa al problema affrontato precedentemente (sezione 218.4) ci si rende immediatamente conto che utilizzando questo metodo di scrittura nel file si possono accodare le informazioni utilizzando poche righe di codice. Ad esmpio: La gestione del file system 2331 0 <html><body> 1 2 <? 3 $f = @fopen("dati_6.txt", "a"); //apre in scrittura. se non esiste lo crea 4 if($f){ 5 echo "<br><br>file <a href=\"dati_6.txt\">dati_6.txt</a> Aperto."; 6 echo "<br><br>Sto salvando i tuoi dati nel file"; 7 8 $frase = "visitatore di 6.php - "; 9 $frase = $frase."il suo IP:".$REMOTE_ADDR." alle ore: ".date("d-m-Y G:i:s")." \n"; 10 11 @fputs($f,$frase); // scrive la frase nel file tramite $f 12 @fclose($f); // è importante chiudere il file 13 14 echo "...... Fatto!"; 15 16 }else{ 17 echo "<br>Errore durante l’apertura del file dati_6.txt"; 18 } 19 ?> 20 21 </body></html> È bene sottolineare che in questo caso non ci sono controlli sulle dimensioni del file di testo generato. Ogni volta che lo script viene eseguito il file ‘dati_6.txt’ aumenta di dimensioni. Se la pagina è molto visitata a lungo andare potrebbe addirittura saturare il disco. Visto che questo è un semplice esercizio e non si ha alcun bisogno dei dati contenuti nel file verrà aggiunto un controllo che elimina il file sele sue dimensioni superano un determinato valore. Ecco una soluzione: 0 <html><body> 1 2 <? 3 $max_file_size = 4000; // dimensione massima in byte 4 5 if(filesize("dati_6.txt") > $max_file_size ){ 6 echo "<br><br><b>Vuoto il file! ha superato il limite</b><br><br>"; 7 $f = @fopen("dati_6.txt", "w"); //lo apre scrittura e lo svuota 8 }else{ 9 $f = @fopen("dati_6.txt", "a"); //lo apre scrittura e appende i dati 10 } 11 if($f){ 12 echo "<br><br>file <a href=\"dati_6.txt\">dati_6.txt</a> Aperto."; 13 echo "<br><br>Sto salvando i tuoi dati nel file"; 14 15 $frase = "visitatore di 6.php - "; 16 $frase = $frase."il suo IP:".$REMOTE_ADDR." alle ore: ".date("d-m-Y G:i:s")." \n"; 17 18 @fputs($f,$frase); // scrive la frase nel file tramite $f 19 @fclose($f); // è importante chiudere il file 20 21 echo "...... Fatto!"; 22 23 }else{ 24 echo "<br>Errore durante l’apertura del file dati_6.txt"; 25 } 26 ?> 27 28 </body></html> Le modifiche sono semplici, è stato aggiunto un ‘if’ che controlla la dimensione del file ‘dati_6.txt’ se è maggiore del valore impostato nella variabile ‘$max_file_size’ apre il file in modalità ‘w’ e quindi ne cancella il contenuto, altrimenti lo apre in modalità ‘a’. In entrambi i casi se il file non esiste viene creato. 2332 La gestione del file system 218.6 Conclusioni Il file system, come appena visto, permette di immagazzinare informazioni su disco dando la possibilità di aggiornarle modificandole o cancellandole. Tuttavia è bene tenere presente che esistono tecnologie relazionali apposite per la gestione di grandi moli di dati che garantiscono maggiori prestazioni e una migliore gestione dello spazio su disco. Tali tecnologie sono le basi di dati alle quali si accede tramite un linguaggio di interrogazione standard noto come SQL1 . Il file rimane comunque uno strumento utile, semplice e immediato, e nel caso di piccole quantità di dati o nel caso in cui non si abbia accesso ad un DBMS2 , può essere preso in considerazione come alternativa alle basi di dati. Programmare in PHP --- Copyright © 2001-2002 Gianluca Giusti -- brdp @ urcanet.it 1 Acronimo di "Structured Query Language" ovvero "linguaggio di interrogazione strutturato". Acronimo di "Data Base Management System " ovvero "Sistema di Gestione di Basi di Dati", è il software che si occupa di rispondere alle istruzioni SQL. 2 Indice analitico del volume ./.efax.rc, 1443 ./.htaccess, 1726 /etc/aliases, 1603, 1650, 1659, 1660 /etc/apache/access.conf, 1720 /etc/apache/httpd.conf, 1711, 1938 /etc/apache/srm.conf, 1715 /etc/apache-ssl/apache.pem, 2175 /etc/apache-ssl/, 2175 /etc/bind/named.ca, 1326 /etc/bind/named.conf, 1324, 1335, 1419 /etc/bind/named.root, 1326 /etc/boa/boa.conf, 1733 /etc/conf.uugetty, 1429 /etc/default/nis, 1505 /etc/default/uugetty, 1429 /etc/dhcp.conf, 1512 /etc/dhcp.leases, 1512 /etc/dhcpc/hostinfo-*, 1515 /etc/dhcpc/resolv.conf, 1515 /etc/efax.rc, 1443 /etc/ethers, 1266 /etc/exports, 1484 /etc/ftpaccess, 1583 /etc/ftpchroot, 1577 /etc/ftpconversions, 1580 /etc/ftphosts, 1590 /etc/ftpusers, 1564, 1577, 1580 /etc/ftpwelcome, 1577 /etc/host.conf, 1309 /etc/hosts, 1310 /etc/hosts.allow, 1472, 1482, 1496, 2046 /etc/hosts.deny, 1472, 1482, 1496, 2046 /etc/hosts.equiv, 1518, 2192 /etc/htdig/htdig.conf, 1853 /etc/httpd/conf/access.conf, 1720 /etc/httpd/conf/httpd.conf, 1711, 1938 /etc/httpd/conf/srm.conf, 1715 /etc/inetd.conf, 1468, 1471 /etc/init.d/nis, 1505 /etc/init.d/setserial, 1359 /etc/ircd/ircd.conf, 1546, 1547 /etc/ircd/ircd.motd, 1547 /etc/issue.net, 1532 /etc/login.access, 2039 /etc/lynx.cfg, 1698 /etc/mail.rc, 1610 /etc/mail/deny, 1658 /etc/mail/deny.db, 1658 /etc/mail/ip_allow, 1657 /etc/mail/LocalIP, 1657 2333 /etc/mail/LocalNames, 1657 /etc/mail/name_allow, 1657 /etc/mail/RelayTo, 1657 /etc/mail/relay_allow, 1657 /etc/mailman/mm_cfg.py, 1686 /etc/mgetty+sendfax/login.config, 1441 /etc/mgetty+sendfax/mgetty.config, 1440 /etc/minicom.users, 1371 /etc/minirc.dfl, 1371 /etc/mirror.defaults, 1869 /etc/motd, 1577 /etc/nail.rc, 1611 /etc/named.conf, 1324, 1335, 1419 /etc/networks, 1311 /etc/news/distrib.paths, 1817 /etc/news/expire.ctl, 1819 /etc/news/inn.conf, 1816 /etc/news/newsfeeds, 1818, 1827, 1829, 1830 /etc/news/nnrp.access, 1820 /etc/nologin, 1577 /etc/nsswitch.conf, 1505, 1506 /etc/ntp.conf, 1539 /etc/pine.conf, 1615 /etc/pine.conf.fixed, 1615 /etc/porttime, 2040 /etc/ppp/chap-secrets, 1379, 1388, 1424 /etc/ppp/ipv6-down, 1381 /etc/ppp/ipv6-up, 1381 /etc/ppp/ip-down.d/, 1396 /etc/ppp/ip-down, 1306, 1381, 1391 /etc/ppp/ip-up.d/, 1396 /etc/ppp/ip-up, 1306, 1381, 1391 /etc/ppp/options, 1379 /etc/ppp/options.ttyS*, 1379 /etc/ppp/pap-secrets, 1379, 1388, 1424 /etc/ppp/peers/wvdial, 1424 /etc/ppp/resolv.conf, 1391 /etc/protocols, 1245, 1298 /etc/queso.conf, 2069 /etc/radvd.conf, 1302 /etc/resolv.conf, 1312, 1419 /etc/rinetd.conf, 1992 /etc/rpc, 1480 /etc/rsyncd.conf, 1901 /etc/rsyncd.secrets, 1904 /etc/sendmail.cf, 1603 /etc/services, 1245 /etc/squid.conf, 1944 /etc/ssh//etc/ssh/ssh_host_dsa_key.pub, 2188 /etc/ssh//etc/ssh/ssh_host_dsa_key, 2188 /etc/ssh//etc/ssh/ssh_host_key.pub, 2188 /etc/ssh//etc/ssh/ssh_host_key, 2188 2334 /etc/ssh//etc/ssh/ssh_host_rsa_key.pub, 2188 /etc/ssh//etc/ssh/ssh_host_rsa_key, 2188 /etc/ssh/shosts.equiv, 2192 /etc/ssh/sshd_config, 2195 /etc/ssh/ssh_config, 2199 /etc/ssh/ssh_known_hosts, 2190 /etc/ssl/certs/apache.pem, 2175 /etc/ssl/certs/telnetd.pem, 2177 /etc/ssmtp/revaliases, 1674 /etc/ssmtp/ssmtp.conf, 1674 /etc/telnetrc, 1532 /etc/usertty, 2037 /etc/webalizer.conf, 1860 /etc/wgetrc, 1875 /etc/wvdial.conf, 1423, 1425 /etc/xinetd.conf, 1475 /etc/yp.conf, 1505, 1506 /etc/ypserv.conf, 1496, 1499 /etc/ypserv.securenets, 1496, 1500 /proc/net/if_inet6, 1298 /tftpboot/, 1536 /usr/lib/yp/makedbm, 1496 /usr/lib/yp/ypinit, 1501 /var/cache/bind/, 1324 /var/lib/news/active, 1821 /var/lib/news/history, 1822 /var/lib/nfs/rmtab, 1484 /var/log/xferlog, 1593 /var/mail/, 1661 /var/spool/mqueue/, 1604 /var/spool/rwho/, 1523 /var/yp/Makefile, 1501 10/100/1000base*, 1236 10/100base*, 1236 10base2, 1239 10base5, 1238 10baseT, 1239 10base*, 1236 6to4, 1295 ABC-nslookup, 2211 accesso remoto, 1518, 2027 accesso sequenziale, 2324 accounting: IP, 1982, 2003 Address Resolution Protocol, 1224 AIDE, 2064 aide.conf, 2064 alias IP, 1255 anycast, 1287, 1294 Apache, 1709, 1938 Apache-SSL, 2175 append, 2330 ARP, 1224, 1265 2335 arp, 1265 array, 2285, 2289 array(), 2289 autorità di certificazione, 2150 Balsa, 1616, 1618 baud, 1375 Boa, 1733 Bobcat, 2212 boolean, 2285, 2287 bot, 1546 bps, 1375 break, 2302, 2308 bridge, 1220 broadcast, 1225 cartella di messaggi, 1620 case, 2302 casella postale, 1620 cavallo di Troia, 2034 certificato, 2150 cfd.conf, 2126 Cfengine, 2104, 2114, 2125 CGI, 1738, 1762 CGI: accesso a una base di dati, 1782, 1789 CHAP, 1379 Chat, 1409 chiave privata, 2131 chiave pubblica, 2131 chroot, 2053, 2054 chrootuid, 2054 ciclo, 2303, 2305, 2305, 2306 cifratura, 2131 class, 2293 cloner, 1546 commutatore di pacchetto, 1240 contabilità del traffico IP, 1982, 2003 count(), 2327 crittografia, 2131 crittografia a chiave pubblica, 2131 crittografia a chiave segreta, 2131 crittografia asimmetrica, 2131 crittografia simmetrica, 2131 Crynwr, 2208 ctlinnd, 1823 CVS, 1906, 1921 datagramma, 1218 date(), 2278, 2289, 2327 DBMS, 2332 DCE, 1362 DHCP, 1510 dhcpcd, 1515 dhcpd, 1512 dhcrelay, 1515 2336 die(), 2295 Dig, 1330 DNS, 1233, 1313, 1316, 1333, 1417, 2024 DNS: alias, 1322, 1343 DNS: record A, 1341 DNS: record A6, 1341 DNS: record AAAA, 1341 DNS: record CNAME, 1343 DNS: record MX, 1341 DNS: record NS, 1340 DNS: record SOA, 1339 dnsserver, 1949 do..while, 2305 domainname, 1496 dominio, nome di, 1232 DOS, 2208 DOS: packet-driver, 2208 DOS: PPP, 2225 DosLynx, 2215 double, 2287 DTE, 1362 echo, 2278 Efax, 1443 else, 2299, 2299 elseif, 2300, 2302 email, 1599, 1622, 1640 escape, 2288 esempio: ppp-chiudi, 1414 esempio: ppp-connetti, 1412 Ethereal, 2091 Ethernet, 1235, 1250, 1257 exicyclog, 1673 Exim, 1659 exportfs, 1484 fax, 1443 fclose(), 2325, 2327, 2330 feof(), 2324, 2325, 2327 Fetchmail, 1625 fgets(), 2325, 2327 file, 2324 file(), 2295, 2325 filesize(), 2330 file_exists(), 2325 filtro di pacchetto IP, 1961, 1994 finger, 1524 Finger, 1524, 2022 fingerd, 1524 firewall, 1951, 1961, 1994 firma digitale, 2131 firma elettronica, 2131 float, 2287 flooder, 1546 2337 foalt, 2285 fopen(), 2324, 2325, 2327, 2330 for, 2305 foreach, 2306 form, 2311 fputs(), 2327, 2330 FQDN, 1232 frame, 1218 freeWAIS, 1841 freeWAIS-sf, 1841 FTP, 1564, 1576, 1579, 1834 ftp, 1565 FTP: anonimo, 1564, 1581, 2026 FTP: riproduzione speculare, 1866 ftpcount, 1594 ftpd, 1576, 1579 ftpwho, 1594 Fully Qualified Domain Name, 1232 function(), 2317, 2322 funzioni, 2315, 2315 gateway, 1220 get, 2311 get, 2311 gettype(), 2282, 2285 Getty_ps, 1428, 1452 Glimpse, 1803 global, 2317 GnomeICU, 1556, 1556 GnuPG, 2138 gpg, 2138 gpgm, 2138 Grepmail, 1620 handshaking, 1361 hash, 2285, 2289 Hayes, 1363 Host, 1329 hosts.nntp, 1826 ht://Dig, 1852 htdigconfig, 1853 htpasswd, 1728 htsearch, 1854 HTTP, 1697, 1709, 1733, 1738 HTTP: autenticazione, 1728 httpd, 1709 ICMP, 1247 icmplog, 2096 ICQ, 1555 IDENT, 2042 identd, 2042 identtestd, 2044 IEEE 802.3, 1235 if, 2287, 2298 2338 Ifconfig, 1249, 1253 imapd, 1623 impronta digitale, 2133 in.fingerd, 1524 in.ftpd, 1576, 1579 in.identd, 2042 in.identtestd, 2044 in.rlogind, 1519 in.rshd, 1520 in.talkd, 1528 in.telnetd, 1532 in.tftpd, 1536 include(), 2297, 2309, 2315 inclusione di file, 2309 incoming.conf, 1826 indicizzazione dei file, 1841 inetd, 1468 Info2www, 1804 INN, 1814 innd, 1822 innfeed.conf, 1827 integer, 2285, 2286 Internet domain socket, 1348, 1351 InterNet News, 1814 Internet Relay Chat, 1544 Internet service daemon, 1468 intero, 2286 interruzione, 2308 ip, 1279, 1279 IP aliasing, 1255 ipchains, 1995, 2005, 2007 IPlogger, 2096 ipop2d, 1623 ipop3d, 1623 Iproute, 1279 IPTables, 1962 IPTraf, 2085 IPv4, 1225, 1929 IPv4: classi, 1227 IPv4: rete privata, 1229 IPv4-compatible IPv6 addresses, 1294 IPv4-mapped IPv6 addresses, 1295 IPv6, 1245, 1286, 1298, 1310 IPv6: FTP, 1574, 1576 IRC, 1544 ircd, 1549 ISO 8802.3, 1235 ISO-OSI, 1218 ISP, 1452 is_array(), 2299 is_double(), 2299 is_integer(), 2299 2339 is_string(), 2299 I-seek-you, 1555 LAN, 1216 Lftp, 1574 Libident, 2044 linea dedicata, 1397, 1402 Links, 1705 Linuxconf, 2029 lista di posta elettronica, 1676 lockvc, 2100 login, 2037 login remoto, 1518, 2027 logoutd, 2040 loop, 2303, 2305, 2305, 2306 loopback, 1228, 1250, 1257 lsh, 2185 LSH, 2182 lshc, 2185 lshd, 2184 lsh-keygen, 2183 lsh-writekey, 2183 Lynx, 1698, 2212 mail, 1607 mailing-list, 1676 Mailman, 1685 mailq, 1604, 1659, 1670 Mailx, 1607 makedbm, 1496 MAN, 1216 man2HTML, 1803 maschera di rete, 1225 mascheramento, 1951 mascheramento IP, 2005 MAU, 1238 mesg, 1527 mgetty, 1438 Mgetty+Sendfax, 1438, 1460 MIME, 1629 Minicom, 1371 MiniTelnet, 2211 Mirror, 1867 mirror, 1866 mmsitepass, 1686 mm_cfg.py, 1686 modem, 1359, 1397, 1402 modem: baud, 1375 modem: bit/s, 1375 modem: bps, 1375 modem: configurazione, 1373 motore di ricerca, 1841 Mpack, 1638 MUA, 1606 2340 multicast, 1287, 1510 Nail, 1611 name server, 1316, 1333 named, 1324 NAT, 1275, 1951, 1986 nc6, 2096 NCSA, 2217 NCSA Telnet, 2217 NE2000, 1236, 2208 Netcat6, 2096 netiquette, 1866, 1887 netmask, 1225 Netstat, 2078 Netstd ftp, 1565 Network Address Translation, 1275, 1951 Network Time Protocol, 1538 newaliases, 1603, 1650 newlist, 1687 news, 1808 news.daily, 1825 NFS, 1484, 2023 NIS, 1491, 2028 nisdomainname, 1496 nnrpd, 1822 nntpget, 1830 nntpsend, 1829 nntpsend.ctl, 1828 nome di dominio, 1232, 1313 NOS, 2228 Nslookup, 1328, 2211 NTP, 1538 ntpd, 1539 ntpdate, 1538 Null-modem, 1362 numero a virgola mobile, 2287 object, 2293 OpenSSH, 2188 OpenSSL, 2162 operatori, 2293 operatori aritmetici, 2293 operatori di assegnazione, 2294 operatori di confronto, 2297 operatori di controllo degli errori, 2295 operatori di incremento e decremento, 2296 operatori logici, 2297 OSI, 1218 pacchetto, 1217 PAP, 1379 PAT, 1275, 1951, 1986 PCroute, 2222 PDU, 1220 percorso di fiducia, 2147 2341 Perl, 1762 Perl: CGI, 1762 Perl: Pg, 1787 phpinfo(), 2278, 2284 Pine, 1611 ping, 1264 pinger, 1949 PLIP, 1243, 1251, 1259, 2208 point-to-point, 1216, 1251, 1259, 1378 Popclient, 1624 POPMail, 2219 Port Address Translation, 1275, 1951 porta, 1245 porta seriale, 1359, 1397 portmap, 1480 post, 2313 post, 2311 posta elettronica, 1599, 1622 PostgreSQL, 1782, 1789 post_max_size, 2313 PPP, 1378, 1400, 1406, 1418, 1423, 1454 pppd, 1378 ppp-chiudi, 1414 ppp-connetti, 1412 PPRD, 2213 print_r(), 2289 proxy, 1419, 1934 proxy trasparente, 1988, 2006 psql, 1783, 1784 punto-punto, 1216, 1251, 1259, 1378 Queso, 2069 Raccess, 2070 Radvd, 1302 rdist, 1893 Rdist, 1888 rete, 1216 rete: configurazione, 1249 rete: geografica, 1216 rete: hardware, 1235 rete: indirizzo IP e nome, 1309 rete: instradamento, 1256, 1267 rete: locale, 1216 rete: metropolitana, 1216 rete: privata, 1229 rete: protocolli, 1245 rete: protocolli di trasporto e di rete, 1245 rete: servizi, 1245 return, 2317, 2322 ricorsione, 2322 rinetd, 1992 ripetitore, 1220, 1237, 1239 riproduzione speculare, 1866 2342 rlogin, 1519 rlogind, 1519 rmlist, 1687 rndc, 1324 Route, 1256, 1260 router, 1220, 1267, 1269 RPC, 2024 rpc.lockd, 1484 rpc.mountd, 1484 rpc.nfsd, 1484 rpc.rquotad, 1484 rpc.rusers, 1524 rpc.rwalld, 1530 rpc.statd, 1484 rpc.yppasswdd, 1496, 1503 rpc.ypxfrd, 1496, 1504 rpcinfo, 1481 rsh, 1520 Rsync, 1895 RS-232C, 1362 rundig, 1853 runq, 1670 rusers, 1524 rwall, 1530 rwalld, 1530 rwho, 1523 rwhod, 1523 safe_finger, 2052 SANTA, 2071 satan, 2075 SATAN, 2071 satan/config/paths.pl, 2073 satan/config/paths.sh, 2073 satan/config/satan.cf, 2073 scp, 2199 SECSH, 2158 Secure Shell, 2158, 2188 Sendmail, 1602, 1650, 1670, 2028 servente di chiavi, 2136 servente: CGI, 1738 servente: Finger, 1524, 2022 servente: FTP, 1576, 1579 servente: HTTP, 1709, 1733 servente: LSH, 2182 servente: Secure Shell, 2188 servizio di risoluzione dei nomi, 1316, 1333 setserial, 1359 settype(), 2282, 2285 Seyon, 1372 showmount, 1488 sicurezza, 2021, 2037, 2099, 2104 sito speculare, 1866 2343 sito virtuale, 1731 SLIP, 1404 SmartList, 1678 SMTP, 1599 Sniffit, 2088 socket, 1348, 1351 socket di dominio Internet, 1348, 1351 socket di dominio Unix, 1348, 1351 sottorete, 1225 SQL, 2332 Squid, 1419, 1942 ssh, 2199 SSH, 2158, 2188 sshd, 2195 SSHDOS, 2212 ssh-keygen, 2188 SSL, 2157, 2162 SSL: Apache, 2175 SSL: SSLwrap, 2178 SSL: Stunnel, 2180 SSL: TELNET, 2177 SSLwrap, 2178 sSMTP, 1674 stateless, 1289 string, 2285, 2288 stringa, 2288 Strutture di controllo, 2297 Stunnel, 2180 subnet router anycast address, 1294 substr(), 2315 supervisore di rete, 1468 switch, 1240 switch, 2302 Talk, 2215 talk, 1528 talkd, 1528 TCP, 1929 TCP/IP, 1222 TCP/IP: accesso remoto, 1518 TCP/IP: DOS, 2208 TCP/IP: informazioni sugli utenti, 1523 TCP/IP: messaggi sul terminale, 1527 TCP/IP: NFS, 1484 TCP/IP: NOS, 2228 TCP/IP: RPC, 1480 TCP/IP: servizi, 1468 TCP/IP: TELNET, 1532 tcpd, 1471 tcpdchk, 2050 tcpdmatch, 2051 tcpdump, 2080 Tcpdump, 2080 2344 tcplog, 2096 TCP wrapper, 1471, 2046 TELNET, 1532, 2217 telnet, 1532 telnetd, 1532 Telnet-SSL, 2177 Telnet NCSA, 2217 TFTP, 1536, 2027 tftp, 1536 tftpd, 1536 TLS, 2157, 2162 Traceroute, 1273 traffico di rete, 2078 trama, 1218 transparent proxy, 1988, 2006 Tripwire, 2057 Trivial FTP, 1536, 2027 trojan, 2034 Trout, 2214 try-from, 2052 tw.config, 2057 UCSPI, 1351 UDP, 1929 UIN, 1555 unicast, 1287 Universal Internet number, 1555 Unix client-server program interface, 1351 Unix domain socket, 1348, 1351 unlink(), 2327 unlinkd, 1949 URI, 1738 URL, 1738 Usenet, 1808 Uuencode, 1630 uugetty, 1428, 1430, 1452 variabili globali, 2317 Variabili http, 2284 variabili locali, 2317 verme, 2034 VH-man2HTML, 1803 virtual host, 1731 virus, 2034 vlock, 2100 W3M, 1707 WAIS, 1841 waisindex, 1844 waissearch, 1844 waisserver, 1841 waisserver.d, 1841 wall, 1527 WAN, 1216 WATTCP, 2209 2345 Webalizer, 1860 Wget, 1874 while, 2303 worm, 2034 write, 1527 WU-FTP, 1834 WvDial, 1423 wvdialconf, 1423 X, 2028 xferstats, 1593 Xinetd, 1474 xlock, 2101 xntpd, 1539 xtrlock, 2101 YP, 1491 ypbind, 1505, 1506 ypcat, 1507 ypchfn, 1507 ypchsh, 1507 ypdomainname, 1496 ypinit, 1501, 1503 ypmatch, 1507 yppasswd, 1507 ypserv, 1496, 1497 ypwhich, 1503, 1507 ypxfr_1perday, 1504 ypxfr_1perhour, 1504 ypxfr_2perhour, 1504 ytalk, 1528 ~/.cvsignore, 1897 ~/.efax.rc, 1443 ~/.fetchmailrc, 1625 ~/.forward, 1526, 1605, 1650, 1659, 1661 ~/.gnome/balsa, 1616 ~/.gnupg/options, 2138 ~/.lsh/identity.pub, 2185 ~/.lsh/identity, 2185 ~/.lsh/known_hosts, 2185 ~/.mailrc, 1610, 1611 ~/.netrc, 1565, 1570 ~/.plan, 1526 ~/.poprc, 1624 ~/.ppprc, 1379 ~/.project, 1526 ~/.rhosts, 1518, 2192 ~/.shosts, 2192 ~/.ssh/authorized_keys, 2193 ~/.ssh/config, 2199 ~/.ssh/identity.pub, 2188 ~/.ssh/identity, 2188 ~/.ssh/id_dsa.pub, 2188 ~/.ssh/id_dsa, 2188 2346 ~/.ssh/id_rsa.pub, 2188 ~/.ssh/id_rsa, 2188 ~/.ssh/known_hosts, 2190 ~/.ssh/random_seed, 2188 ~/.telnetrc, 1532 ~/.wgetrc, 1875 ~ftp/, 1577 ~/.pinerc, 1615 $CFINPUTS, 2105 $CVSIGNORE, 1897 $CVSROOT, 1906, 1909 $CVS_RSH, 1924 $ftp_proxy, 1936 $gopher_proxy, 1936 $HTTP_GET_VARS, 2314 $HTTP_POST_VARS, 2314 $http_proxy, 1936 $HTTP_REFERER, 2284 $HTTP_USER_AGENT, 2284 $MAIL, 1605, 1606, 1661 $NNTPSERVER, 1816 $ORGANIZATION, 1816 $REMOTE_ADDR, 2284, 2327 $RESOLV_HOST_CONF, 1310 $RESOLV_SERV_MULTI, 1310 $RESOLV_SERV_ORDER, 1310 $RSYNC_PASSWORD, 1900 $RSYNC_RSH, 1897 $SCRIPT_NAME, 2284 $SERVER_NAME, 2284 $wais_proxy, 1936 2347 2348 Appunti di informatica libera 2003.01.01 Volume IV Scrivere 2349 Appunti Linux Copyright © 1997-2000 Daniele Giacomini Appunti di informatica libera Copyright © 2000-2003 Daniele Giacomini Via Morganella Est, 21 -- I-31050 Ponzano Veneto (TV) -- daniele @ swlibero.org Le informazioni contenute in questa opera possono essere diffuse e riutilizzate in base alle condizioni poste dalla licenza GNU General Public License, come pubblicato dalla Free Software Foundation. In caso di modifica dell’opera e/o di riutilizzo parziale della stessa, secondo i termini della licenza, le annotazioni riferite a queste modifiche e i riferimenti all’origine di questa opera, devono risultare evidenti e apportate secondo modalità appropriate alle caratteristiche dell’opera stessa. In nessun caso è consentita la modifica di quanto, in modo evidente, esprime il pensiero, l’opinione o i sentimenti del suo autore. L’opera è priva di garanzie di qualunque tipo, come spiegato nella stessa licenza GNU General Public License. Queste condizioni e questo copyright si applicano all’opera nel suo complesso, salvo ove indicato espressamente in modo diverso. The informations contained inside this work can be spread and reused under the terms of the GNU General Public License as published by the Free Software Foundation. If you modify this work and/or reuse it partially, under the terms of the license, the notices about these changes and the references about the original work, must be evidenced conforming to the work characteristics. IN NO EVENT IS ALLOWED TO MODIFY WHAT ARE CLEARLY THE THOUGHTS, THE OPINIONS AND/OR THE FEELINGS OF THE AUTHOR. This work 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. These conditions and this copyright apply to the whole work, except where clearly stated in a different way. Una copia della licenza GNU General Public License, versione 2, si trova nell’appendice A. A copy of GNU General Public License, version 2, is available in appendix A. 2350 The main distribution for Appunti di informatica libera is described below. For every distribution channel the maintainer’s name and address is also reported. Internet • direct reading: <http://a2.swlibero.org/> download: <ftp://a2.swlibero.org/a2/> and <http://a2.swlibero.org/ftp/> Michele Dalla Silvestra, mds @ swlibero.org • direct reading: <http://appuntilinux.torino.linux.it/> download: <ftp://ftp.torino.linux.it/appunti-linux/> Carlo Perassi, carlo @ linux.it • direct reading: <http://sansone.crema.unimi.it/linux/a2/HTML/> download: <http://sansone.crema.unimi.it/linux/a2/> Fabrizio Zeno Cornelli, zeno @ filibusta.crema.unimi.it • direct reading: <http://www.pctime.it/servizi/appunti-linux/> download: <http://www.pctime.it/servizi/appunti-linux/a2-prelievo/> Franco Lazzero, PCTIME, pctime @ pctime.net • direct reading: <http://www.a2.prosa.it/> download: <ftp://ftp.a2.prosa.it/> Davide Barbieri, paci @ prosa.it • direct reading: <http://linux.pueste.it/> download: <http://linux.pueste.it/filearea/AppuntiLinux/> David Pisa, david @ iglu.cc.uniud.it • direct reading: <http://www.informasiti.com/Appunti/HTML/> download: <http://www.informasiti.com/Appunti/> Claudio Neri, Sincro Consulting, neri.c @ sincroconsulting.com GNU distributions • GNU/Linux Debian <http://packages.debian.org/appunti-informatica-libera> Massimo Dal Zotto, dz @ cs.unitn.it Italian magazine’s CD-ROM • inter-punto-net <http://www.interpuntonet.it> Michele Dalla Silvestra, mds @ swlibero.org • Internet News <http://inews.tecnet.it> Francesco Facconi, francescofacconi @ libero.it Fabio Ferrazzo, fabio.fr @ tiscalinet.it • Linux Magazine <http://www.edmaster.it/prodotti/linux/ult-riv.html> Emmanuele Somma, esomma @ ieee.org La diffusione di questa opera è incoraggiata in base ai termini della licenza. The spread of this work is encouraged under the terms of the license. 2351 Parte xli Editoria e stile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2355 219 Formati standard della carta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2356 220 Nozioni elementari di tipografia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2359 221 Stile letterario . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2365 222 Evoluzione dell’editoria elettronica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2389 Parte xlii Codifica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2393 223 Introduzione alla codifica universale dei caratteri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2394 224 Esempi di codifica dei caratteri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2405 Parte xliii PostScript: un linguaggio per la composizione finale . . . . . . . . . . . . . . . . . 2411 225 Linguaggio PostScript: introduzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2412 226 PostScript: espressioni e funzioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2428 227 PostScript: caratteri da stampa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2435 228 Esempi di funzioni PostScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2443 Parte xliv TeX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2449 229 teTeX: la distribuzione Unix di TeX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2453 230 TeX: introduzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2464 231 TeX: caratteri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2483 232 TeX: la pagina . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2492 233 TeX: paragrafi, righe, spazi, scatole e linee . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2498 234 TeX: tabelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2522 235 TeX: ambienti matematici . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2532 236 LaTeX: introduzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2550 237 LaTeX: struttura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2568 238 LaTeX: la pagina . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2575 239 LaTeX: caratteri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2583 240 LaTeX: blocchi di testo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2590 241 LaTeX: spazi e scatole . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2603 242 LaTeX: riferimenti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2613 243 LaTeX: tabelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2624 244 LaTeX: figure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2635 245 LaTeX: ambienti matematici . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2641 246 LaTeX: file esterni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2658 Parte xlv Texinfo: lo standard della documentazione GNU . . . . . . . . . . . . . . . . . . . . . . 2661 2352 247 Introduzione a Texinfo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2662 248 Texinfo: libro e ipertesto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2678 Parte xlvi SGML: un linguaggio per l’editoria e non solo . . . . . . . . . . . . . . . . . . . . . . . 2687 249 SGML: introduzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2689 250 Elaborazione SGML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2717 251 Dichiarazione SGML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2740 252 SGMLtools 1.0/LinuxDoc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2749 253 DebianDoc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2762 254 DocBook: introduzione ai suoi strumenti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2768 Parte xlvii Sgmltexi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2773 255 Sgmltexi: installazione e utilizzo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2774 256 Sgmltexi: struttura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2780 257 Sgmltexi: contenuti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2796 258 Corrispondenza tra Texinfo e Sgmltexi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2810 Parte xlviii HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2833 259 URI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2835 260 HTML: aspetti generali . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2843 261 HTML: corpo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2855 262 CSS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2865 263 HTML2ps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2873 264 Introduzione a Amaya . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2884 265 HTMLDOC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2889 266 Essere presenti su Internet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2899 Parte xlix XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2903 267 XML: cenni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2904 268 XHTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2910 Parte l Controllo dell’ortografia e dello stile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2913 269 Analisi lessicale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2914 270 Analisi sintattica e stilistica con Textchk . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2921 Parte li Alml . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2929 271 Alml: preparazione e visione generale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2930 272 Il documento secondo Alml . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2946 273 Entità ISO gestite da Alml . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2981 2353 274 Stile di scrittura del sorgente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2986 Parte lii Annotazioni particolari riferite all’opera «Appunti di informatica libera» 2991 275 Gestione di «Appunti di informatica libera» . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2992 276 Convenzioni di «Appunti di informatica libera» . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2996 277 Glossario stilistico di «Appunti di informatica libera» . . . . . . . . . . . . . . . . . . . . . . . . . . . 3008 Parte liii Sistemi vari di composizione elettronica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3049 278 Introduzione a *roff . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3051 279 Introduzione a Lout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3077 280 Introduzione a HieroTeX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3109 281 Trasformazione in altri formati . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3128 Indice analitico del volume . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3131 2354 Parte xli Editoria e stile 219 Formati standard della carta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2356 219.1 Caratteristiche fondamentali dello standard ISO 216 . . . . . . . . . . . . . . . . . . . . . . 2356 219.2 Utilizzo pratico dei vari formati ISO 216 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2357 219.3 Formati multipli . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2358 219.4 Riferimenti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2358 220 Nozioni elementari di tipografia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2359 220.1 Caratteri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2359 220.2 Tipometria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2360 220.3 Il carattere nel software di composizione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2362 220.4 Problemi legati ai caratteri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2364 220.5 Riferimenti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2364 221 Stile letterario . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2365 221.1 Uniformità . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2365 221.2 Regole di composizione del testo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2365 221.3 Traduzioni e termini stranieri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2374 221.4 Strafalcioni comuni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2376 221.5 Unità di misura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2378 221.6 Rappresentazione di valori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2380 221.7 Stile tipografico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2381 221.8 Riferimenti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2387 222 Evoluzione dell’editoria elettronica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2389 222.1 Evoluzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2389 222.2 Codifica del testo (markup) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2390 222.3 SGML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2391 2355 Capitolo 219 Formati standard della carta Lo standard ISO 2161 definisce i formati di carta più comuni, secondo una logica molto semplice. Vale la pena di riassumere brevemente i concetti legati a questo standard, ancor prima di affrontare altri problemi legati alla scrittura. 219.1 Caratteristiche fondamentali dello standard ISO 216 Nello standard ISO 216, i lati del foglio di carta hanno un rapporto fisso, dove il lato lungo è pari alla radice quadrata di due (circa 1,4142) per la lunghezza del lato corto (figura 219.1). Figura 219.1. Il rapporto tra i lati di un foglio ISO 216. .---------------. | | | | | | | | b = radq(2) * a | | b | | | | | | | | ‘---------------’ a .---------------. | | | | a | | | | |---------------| | | | | | | a | | ‘---------------’ b Questo rapporto ha una proprietà importante, che consente al foglio di carta di essere dimezzato sul lato lungo, oppure di essere raddoppiato sul lato corto, mantenendo lo stesso rapporto tra i lati. Lo standard ISO 216 definisce tre diverse serie di questi formati, ognuna delle quali parte da una dimensione di partenza, generando le altre dimensioni suddividendo quella precedente a metà, sul lato lungo. La serie A, ha come punto di riferimento il formato A0, corrispondente a un foglio con un’area di un metro quadro, tuttavia non si tratta del formato più grande, che è ottenuto raddoppiando due volte il formato A0, ottenendo così quattro metri quadri. La tabella 219.1 elenca le dimensioni di tutti i formati delle tre serie, denominate A, B e C. Come si può osservare, i valori sono approssimati al millimetro, in aderenza al SI (sezione 221.5). Tabella 219.1. ISO 216: formato A, B e C. A 4A0 2A0 A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 1 mm 1682 x 2378 1189 x 1682 841 x 1189 594 x 841 420 x 594 297 x 420 210 x 297 148 x 210 105 x 148 74 x 105 52 x 74 37 x 52 26 x 37 B --B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 B10 mm --1000 x 1414 707 x 1000 500 x 707 353 x 500 250 x 353 176 x 250 125 x 176 88 x 125 62 x 88 44 x 62 31 x 44 Altri standard analoghi a ISO 216 sono UNI 936 e DIN 476. 2356 C --C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 C10 mm --917 x 1297 648 x 917 458 x 648 324 x 458 229 x 324 162 x 229 114 x 162 81 x 114 57 x 81 40 x 57 28 x 40 Formati standard della carta 2357 219.2 Utilizzo pratico dei vari formati ISO 216 Tabella 219.2. Esempi di utilizzo pratico dei vari formati. Formati A0, A1 A2, A3 A4 A5 C4 C5 C6 B4, A3 Utilizzo Disegno tecnico; poster. Disegno; diagrammi; tabelle di grandi dimensioni. Lettere; riviste; cataloghi; carta per stampanti comuni e per fotocopiatrici. Blocchi per appunti. Buste per il formato A4. Buste per il formato A4 piegato a metà. Buste per il formato A4 piegato due volte. Giornali. La percentuale di ingrandimento o di riduzione di un formato per ottenerne un altro, si determina facilmente, tenendo conto che si sta facendo riferimento all’ampiezza e all’altezza del foglio, non alla sua area. In pratica, riducendo un formato A4 al 50 %, si ottiene un formato A6, mentre per arrivare al formato A5 occorre usare una riduzione al 71 %. In altri termini, 71 %, ovvero 0,71, approssima la radice quadrata di 0,5. La tabella 219.3 riepiloga alcune trasformazioni tipiche, da un formato a un altro dello standard ISO 216. Tabella 219.3. Esempi di ingrandimento e riduzione dei formati più comuni. Trasformazione richiesta da An a An +1 da Bn a An da An a Bn da Bn a An -1 da An a An -1 rapporto sqrt(0,5) sqrt(sqrt(0,5)) sqrt(sqrt(2)) sqrt(sqrt(2)) sqrt(2) percentuale (approssimata) 71 % 84 % 119 % 119 % 141 % La massa di un foglio di serie A, può essere determinata facilmente, sapendo che A0 ha una superficie di un metro quadro. In pratica, basta conoscere la densità superficiale della carta (la cosiddetta grammatura) che si esprime normalmente in grammi per metro quadro, dividendone opportunamente il valore: l’An avrà una massa pari a 2-n volte quella dell’A0. Per esempio, la massa di un foglio A4 sarà 2-4 volte quella di un A0; ovvero 1/16; se la grammatura è 80 g/m2, la massa di un foglio A4 è 5 g. Le dimensioni dei fogli delle tre serie ISO 216 possono essere determinate anche attraverso delle formule matematiche, come mostrato nella tabella 219.4. Si osservi che le misure che si ottengono sono espresse in metri. Tabella 219.4. Formule per calcolare le dimensioni della carta secondo lo standard ISO 216. Formato An Bn Cn Ampiezza in metri 2(-1/4-n /2) 2(-n /2) 2(-1/8-n /2) Altezza in metri 2(1/4-n /2) 2(1/2-n /2) 2(3/8-n /2) Formati standard della carta 2358 219.3 Formati multipli Quando non si può utilizzare un formato in cui il rapporto tra la lunghezza dei lati sia quello delle serie A, B o C comuni, si possono usare dei multipli di uno di questi formati. Come si vede nella figura 219.2, si tratta di affiancare più fogli di un certo formato, estendendo il lato corto. Questi formati estesi si indicano come An xm , dove m rappresenta quanti fogli di tipo An affiancare. Per esempio, il formato A3 è equivalente al formato A4x2. Figura 219.2. Formati multipli An xm . .---------------------------------------------------------------. | | | | | | | | | | | | | | | | | | | | | An | An | An | An | | | | | | | | | | | | | | | | | | | | | ‘---------------------------------------------------------------’ <--------------------------- m volte --------------------------> 219.4 Riferimenti • Markus Kuhn, International standard paper sizes <http://www.cl.cam.ac.uk/~mgk25/iso-paper.html> • Guide to international paper sizes, Concise tables of measurements, EDS Inc., 1997-2000 <http://www.twics.com/~eds/paper/papersize.html> • R. Smith, F. Wright, T. Hastings, S. Zilles, J. Gyllenskog, RFC 1759: Printer MIB, Appendix B - Media size names from ISO/IEC 10175 Document printing architecture, 1995 <http://www.cis.ohio-state.edu/cgi-bin/rfc/rfc1759.html> <http://www.cis.ohio-state.edu/cs/Services/rfc/rfc-text/rfc1759.txt> • T. Hastings, R. Herriot, R. deBry, S. Isaacson, P. Powell, RFC 2911: Internet printing protocol/1.1: model and semantics, Appendix C: "media" keyword values, 2000 <http://www.cis.ohio-state.edu/cgi-bin/rfc/rfc2911.html> <http://www.cis.ohio-state.edu/cs/Services/rfc/rfc-text/rfc2911.txt> Appunti di informatica libera 2003.01.01 --- Copyright © 2000-2003 Daniele Giacomini -- daniele @ swlibero.org Capitolo 220 Nozioni elementari di tipografia Prima di studiare un programma di editoria elettronica conviene conoscere almeno qualche nozione di tipografia. Studiando la natura del problema si può comprendere la ragione di alcuni comportamenti dei programmi più raffinati che rispecchiano nella loro impostazione la filosofia della tipografia tradizionale. 220.1 Caratteri Il carattere è qualunque segno grafico utilizzato in tipografia per rappresentare le lettere, i segni di interpunzione, le cifre e altri grafemi. La conoscenza delle caratteristiche fondamentali del carattere da stampa è necessaria per poter comprendere il funzionamento e la logica dei programmi di composizione tipografica. Sul carattere si possono distinguere diversi aspetti, in particolare: • specie alfabetica; • stile, o gruppo stilistico; • serie alfabetica, o variante di serie; • scala dimensionale. Al di sopra di questa classificazione sta eventualmente il genere, intendendo con questo la distinzione in base ai suoi componenti: segni alfabetici, segni paralfabetici, segni estralfabetici, fregi, iconografie, paraiconografie. 220.1.1 Specie alfabetica La specie è una collezione di segni di un tipo di scrittura. Per quanto ci riguarda, la specie alfabetica comune è quella dell’alfabeto latino. All’interno di una specie alfabetica si possono distinguere diverse collezioni alfabetiche, per esempio come nella distinzione tra lettere maiuscole e minuscole che avviene nell’alfabeto latino. Dalla differenza tra gli alfabeti nasce a volte la necessità di rendere un testo attraverso un alfabeto alternativo. La traslitterazione è il procedimento di traslazione da un sistema alfabetico a un altro, in modo da ricomporre un testo facendo uso di un sistema alfabetico diverso da quello originale. La traslitterazione punta a riprodurre un testo in modo che sia possibile in qualsiasi momento il procedimento inverso per riottenere il testo originale. Il caso più comune in cui si ha la necessità di utilizzare la traslitterazione è quello della citazione in cui l’originale utilizza un alfabeto esotico per il quale non si dispone del carattere tipografico. Come si può immaginare, la traslitterazione è regolata da norme internazionali. 220.1.2 Gruppo stilistico Una volta definita la specie di un carattere si possono distinguere delle varianti che riguardano lo stile, ovvero il disegno e il suo gusto estetico. Sull’alfabeto latino sono stati realizzati una quantità così grande di stili diversi che è difficile persino riuscire a classificarli. In generale vi si fa riferimento attraverso il nome. Gli stili più noti nella composizione elettronica sono: Times, Helvetica e Courier. 2359 2360 Nozioni elementari di tipografia I tre nomi citati rappresentano oggi, simbolicamente, le caratteristiche fondamentali di uno stile: la presenza o l’assenza di grazie e la proporzionalità o meno della larghezza dei segni.1 Le grazie sono dei piedini terminali che hanno lo scopo di abbellire il carattere e di guidare la vista durante la lettura. Il Times è il tipico stile con grazie, mentre Helvetica è il suo opposto. I segni dei caratteri da stampa sono generalmente di larghezza diversa; solo le prime forme di scrittura meccanica, come la macchina da scrivere e le prime stampanti, hanno creato la necessità di utilizzare dei simboli a larghezza uniforme. Il Courier è il rappresentante di questo tipo di stile a larghezza fissa. In generale, uno stile riguarda esclusivamente un genere alfabetico, ma quando uno stile assume importanza e notorietà, può succedere che venga adottato anche da altri generi. Per questo si può distinguere tra Times Roman (Times New Roman), Times Greco, Times Cirillico e altri. Il primo tra quelli citati è ovviamente il Times dell’alfabeto latino. 220.1.3 Serie La serie alfabetica, o la variante di serie, rappresenta una distinzione all’interno di uno stile, in base alla forma . Le forme comuni di uno stesso stile riguardano la pendenza, il tono e la larghezza. • La pendenza si riferisce all’inclinazione delle aste e si distingue generalmente tra tondo, che rappresenta un carattere con aste verticali, e corsivo in cui le aste sono inclinate in avanti. Generalmente, l’aspetto dei caratteri di un corsivo, pur restando all’interno della stesso stile, è abbastanza diverso da quello del tondo. Quando si utilizza un sistema di composizione elettronico può capitare di avere a disposizione uno stile nel quale manchi il corsivo, che però viene ottenuto in qualche modo distorcendo il tondo. In questo caso si parla preferibilmente di carattere «inclinato» in modo volutamente generico. • Il tono, o lo spessore, rappresenta l’intensità del carattere che si percepisce visivamente. Essendo un concetto che deriva dalla stampa con inchiostro nero, si distingue generalmente tra chiarissimo , chiaro, nero (neretto) e nerissimo . • La larghezza è una caratteristica di cui dispongono solo alcuni stili, ovvero li può riguardare direttamente, nel senso che uno stile per sua natura può essere «stretto» o «largo». In base alla larghezza si distinguono solitamente: lo strettissimo, lo stretto, il normale, il largo e il larghissimo . È bene chiarire che ogni stile può disporre o meno di varianti seriali adatte. Alcuni stili, spesso riferiti a specie alfabetiche simboliche, dispongono di una serie unica.2 1 Questi tre stili sono molto importanti, in parte per motivi storici, ma soprattutto perché sono quelli che si hanno a disposizione più di frequente. 2 Alcuni sistemi di composizione riescono a trarre il corsivo e il neretto da stili che per loro natura non hanno tali varianti. Per ottenerlo si utilizzano tecniche di deformazione e di trascinamento. In generale sarebbe bene evitare di sfruttare tali possibilità, dal momento che se uno stile non dispone di una serie, significa che non è adatto per quella. Nozioni elementari di tipografia 2361 220.2 Tipometria La tipometria è la misurazione degli elementi che riguardano la composizione e l’impaginazione. Le voci più importanti sono costituite dai corpi (l’altezza dei caratteri), dalla spaziatura, dall’interlinea, dalla giustezza e dalla giustificazione. In breve, il corpo è l’altezza del carattere, la spaziatura è la distanza tra una parola e l’altra in una riga, l’interlinea è lo spazio verticale aggiuntivo tra le righe, la giustezza è lo spazio orizzontale che le righe di testo hanno a disposizione, la giustificazione è il procedimento di regolazione della spaziatura e dell’interlinea in modo da ottenere un allineamento delle righe con i margini (sia in orizzontale che in verticale). 220.2.1 Corpo, dimensioni e scala La dimensione del carattere si misura in senso verticale e si definisce corpo. Per misurare il corpo e le altre dimensioni che riguardano i caratteri si possono utilizzare diverse unità di misura, ma quando si tratta di sistemi di composizione elettronica a mezzo di software, è molto probabile che si disponga solo del pica e del punto anglo-americano: • 1 pica = 1/6 di pollice; • 1 punto = 1/12 di pica = 1/72 di pollice. Per comprendere cosa sia il corpo di un carattere è bene descrivere le varie componenti dell’altezza di questo. La figura 220.1 mostra schematicamente la parola «Agglomerato» (abbreviata) suddivisa orizzontalmente secondo le componenti verticali della dimensione del carattere. Figura 220.1. Le dimensioni del carattere. _____________________________________________________________________ spalla superiore _____________________________________________________________________ /\ parte ascendente | | ______/ \_______________________| |_______________________________ / \ /--\/ /--\/ | | /--\ /--\ /--\ parte /------\ | | | | | | | | | | | mediana __ / \___\--/|____\--/|___|___|____\--/____| | |__*_____ | | parte discendente ____________________/________/_______________________________________ spalla inferiore _____________________________________________________________________ ^ | | | | | corpo | | | | v Il carattere si appoggia su una linea che rappresenta la base della «parte mediana»; le lettere come la «l» si alzano occupando anche la «parte ascendente»; altre, come la «g», si allungano in basso a occupare la «parte discendente». Il corpo del carattere include anche uno spazio aggiuntivo: la «spalla». Si distingue una spalla superiore, che è uno spazio minimo sopra la parte ascendente, e la spalla inferiore, che si trova al di sotto della parte discendente (nella figura la spalla è molto grande, in proporzione, rispetto alla realtà). La distanza tra la base di una riga (la base della parte mediana) e la base di quella successiva dovrebbe essere superiore o al minimo uguale alla grandezza del corpo. Quando questa distanza è superiore, lo spazio aggiuntivo è l’interlinea . Con i sistemi di composizione elettronica per mezzo di software, si misura generalmente lo spazio tra le basi delle righe ed è ammissibile anche l’utilizzo di distanze inferiori all’altezza del carattere, ottenendo in pratica una sovrapposizione della parte mediana inferiore di una riga con la parte mediana superiore di quella successiva. La rappresentazione di un carattere con un corpo di una data dimensione dipende dalla disponibilità di questo. Con i sistemi tipografici tradizionali era necessario disporre di una serie di caratteri mobili differenti, distinti in base a una scala. Con i sistemi di composizione elettronica 2362 Nozioni elementari di tipografia via software si possono trovare dei caratteri riproducibili in qualsiasi corpo, eventualmente generando dei file opportuni per la scala richiesta. Tuttavia, in presenza di dimensioni particolarmente piccole si rischia di perdere dei dettagli importanti dei segni che compongono lo stile utilizzato e, di conseguenza, potrebbe essere preferibile l’utilizzo di una variante dello stile che sia più adatta alle dimensioni ridotte. 220.2.2 Giustezza, spaziatura e giustificazione orizzontale La giustezza è lo spazio orizzontale a disposizione delle righe di testo; in altri termini, è la larghezza della colonna all’interno della quale si può distribuire il testo. La spaziatura è lo spazio tra la fine di una parola e l’inizio di quella successiva. Nei testi in italiano, la spaziatura è uniforme, senza eccezioni, a differenza della tradizione tipografica di altri paesi. Per esempio, la spaziatura dopo un punto fermo è esattamente uguale a quella di qualunque altra situazione. Quando si utilizza il sistema di composizione TeX per scrivere un testo in italiano, si dovrebbe inserire il comando ‘\frenchspacing’ per evitare anomalie nella spaziatura. Quando si vuole ottenere un allineamento del testo all’inizio e alla fine della giustezza, si parla di giustificazione (orizzontale). Per ottenerla, è necessario che la spaziatura sia adattata in modo da arrivare a questo risultato. La giustificazione orizzontale è solo una delle scelte stilistiche che il tipografo ha a disposizione: non si tratta di una convenzione obbligatoria. 220.2.3 Giustificazione verticale Come nel caso della giustificazione orizzontale, ci può essere la necessità o l’opportunità di adattare l’interlinea in modo da riempire completamente le pagine. Ciò si ottiene attraverso la giustificazione verticale. 220.3 Il carattere nel software di composizione Utilizzando i programmi di composizione tipografica si è costretti generalmente a fare i conti con la terminologia dei paesi di lingua inglese e con altri problemi legati alla rappresentazione simbolica dei segni all’interno del software. La tradizione tipografica di questi ha generato dei termini che non sono perfettamente traducibili con concetti della tradizione italiana, per cui si utilizzano alcuni termini di origine anglofona, eventualmente tradotti in modo letterale. 220.3.1 Terminologia In inglese si utilizza normalmente il termine font per fare riferimento al carattere tipografico. In generale si preferisce non tradurre questo termine in qualcosa che riguardi la tradizione tipografica italiana, mantenendo piuttosto il termine inglese invariato, oppure utilizzando la forma fonte . Se il contesto non richiede un’aderenza perfetta con il termine originale inglese, si possono usare forme meno impegnative come «carattere», «tipo di carattere», «carattere tipografico» o «carattere da stampa». Nozioni elementari di tipografia 2363 220.3.2 Caratteristiche di una fonte La fonte tipografica, intesa come il carattere per il software applicativo di composizione, ha una serie di caratteristiche, alcune delle quali sono fondamentali. • foundry , fonderia La fonderia è il produttore di una fonte, cioè chi ha creato la tipizzazione, pur senza esserne il disegnatore. Per fare un esempio comune, Adobe è la fonderia dello stile Times New Roman. • family , famiglia La famiglia del carattere, inteso come traduzione del termine font family, corrisponde simultaneamente alla specie e allo stile del carattere. In altri termini, rappresenta sia la specie alfabetica che lo stile. Per fare un esempio, la famiglia Times New Roman è un carattere di specie latina e di stile Times. • All’interno di una famiglia si distinguono normalmente le serie riferite alla forma: spessore (weight), inclinazione (slant) e larghezza (set, o width). • codifica La codifica rappresenta l’elemento nuovo più importante nelle caratteristiche di un carattere tipografico per l’elaborazione via software. Il problema viene descritto nella prossima sezione. 220.3.3 Codifica L’utilizzo dei caratteri con i sistemi di composizione basati sul software richiede un abbinamento tra segni e simboli binari. Questo abbinamento è definito dalla codifica. Il problema si può intendere meglio se si pensa a un programma a composizione differita. In questi casi si parte da un file sorgente, scritto probabilmente secondo la codifica ISO 8859-1, con il quale il programma deve comporre il risultato, utilizzando le fonti a disposizione. La fonte tipografica utilizzata dal programma di composizione è contenuta normalmente all’interno di file, da cui questo estrae le informazioni necessarie attraverso un riferimento dato da un codice numerico. In condizioni normali, il programma di composizione fa riferimento al simbolo binario utilizzato nel sorgente per ottenere il segno corrispondente all’interno della fonte utilizzata (eventualmente attraverso una qualche traslazione). In pratica, alla lettera «A» nel sorgente dovrebbe corrispondere la lettera «A» della fonte che si sta utilizzando, ma se la fonte è organizzata in modo differente, si potrebbe ottenere qualcosa di diverso. Questo problema si avverte di solito quando si utilizza una famiglia di caratteri che fa riferimento a una specie simbolica, o comunque a un alfabeto che non ha alcuna corrispondenza con la codifica utilizzata nel sorgente. In questi casi, di solito, per rappresentare i segni si può fare uso di comandi speciali interpretati opportunamente dal programma di composizione. Un programma di composizione potrebbe disporre di fonti che hanno solo una corrispondenza parziale con la codifica utilizzata per scrivere il sorgente, per esempio, potrebbero mancare alcuni segni che vengono messi a disposizione attraverso altre fonti. Il problema viene riproposto nel capitolo 223, dedicato alla codifica universale. Nozioni elementari di tipografia 2364 220.4 Problemi legati ai caratteri Nelle origini della tipografia, molti caratteri mobili rappresentavano l’unione di più lettere o altri segni in logotipo (cioè l’unione in un simbolo unico). L’unione di questi derivava da delle consuetudini stilistiche o dalla forma dei segni adiacenti che per qualche motivo potevano richiedere un avvicinamento o un adattamento. Il legato (in inglese ligature) è l’unione di due o più segni per motivi storici o estetici; i più comuni sono le sequenze «fi», «fl» e «ffi», dove le lettere vengono avvicinate in modo particolare fino a unirsi o a inglobarsi. Alcune forme di legato si sono tradotte in segni indipendenti, come nel caso di «AE» che si è trasformato in «Æ», «sz» che nella lingua tedesca è ormai «ß» e anche «et» (latino) che è divenuto «&», ovvero l’attuale e-commerciale. L’avvicinamento delle lettere, era ed è motivato dalla forma di queste, per evitare il formarsi di vuoti visivi che potrebbero creare difficoltà alla lettura. I casi più comuni sono le sequenze «AV», «AT», «AY». 220.5 Riferimenti • Scienza, tecnologia e arte della stampa e della comunicazione, Arti poligrafiche europee <http://www.apenet.it/grafica/libri/Grafica/Grafica01/indice02.html> <http://www.apenet.it/grafica/libri/Grafica/Grafica02/indice02.html> <http://www.apenet.it/grafica/libri/Grafica/Grafica03/indice02.html> • Scienza, tecnologia e arte della stampa e della comunicazione: Giuseppe Pellitteri, Luigi Farinelli, Grafismi, Arti poligrafiche europee <http://www.apenet.it/grafica/libri/Grafica/Grafica01/1123.html> Appunti di informatica libera 2003.01.01 --- Copyright © 2000-2003 Daniele Giacomini -- daniele @ swlibero.org Capitolo 221 Stile letterario Questo capitolo, vuole essere solo un riferimento essenziale alla definizione di uno stile letterario e il contenitore di una piccola raccolta di regole, che dovrebbero semplificare la vita di chi scrive documenti elettronici. L’autore di questo documento non ha una competenza specifica su questo problema; tuttavia, è importante almeno affrontare l’argomento sottolineando alcuni concetti importanti.1 221.1 Uniformità Il concetto di stile letterario potrebbe essere espresso semplicemente spiegando l’esigenza di realizzare un documento uniforme : sia dal punto di vista visivo, sia dal punto di vista espressivo. Questo coinvolge quindi l’aspetto grammaticale (ortografia, sintassi, lessico, ecc.) e l’aspetto tipografico (impaginazione, tipi di carattere, dimensione, ecc.) o artistico. L’esigenza di un’uniformità visiva deriva dal piacere e dal rilassamento che può dare al lettore un documento impaginato e strutturato in un modo ordinato e chiaro, per la facilità nella lettura che ne deriva. Nello stesso modo è importante l’uniformità grammaticale, cosa particolarmente delicata in una lingua come la nostra in cui sono consentite molte variazioni, data la varietà linguistico-culturale delle varie regioni. Il novello scrittore di documentazione tecnica, che scrive e impagina senza l’aiuto di un editore, tende a comprendere l’esigenza di uno stile tipografico, dimenticando che esiste anche uno stile espressivo-grammaticale. Il problema dell’uniformità stilistica si accentua quando si deve collaborare alla realizzazione di un progetto letterario. L’uniformità non è più solo un fatto di coerenza personale, ma di coerenza complessiva di tutto il gruppo. La coordinazione dei vari collaboratori è un problema delicato e diviene essenziale la stesura di uno standard letterario complessivo. Alle volte questo ferisce la sensibilità di alcuni collaboratori e genera discussioni senza fine e senza soluzione.2 221.2 Regole di composizione del testo Il modo migliore per definire uno stile grammaticale è lo studio su un testo di grammatica. Qui si vogliono solo raccogliere alcuni punti essenziali che non possono essere ignorati. In effetti, il tipico autore di testi a carattere tecnico, specialmente quando non si tratta di un’attività professionale remunerata, ha un’ottima conoscenza dell’argomento trattato e una pessima padronanza della lingua. 221.2.1 Punteggiatura e spaziatura La punteggiatura si compone di quei simboli che consentono di separare le parole e di delimitare le frasi. 1 Come sempre, tutte le segnalazioni di errore sull’ortografia, la sintassi e il contenuto di questo documento, sono gradite. :-) 2 Il vero artista è colui che crea qualcosa di nuovo e non accetta di sottostare alle regole generali. È evidente quindi che costui non potrà lavorare in un gruppo perché non si sottometterà mai alle regole poste dagli altri o dalla consuetudine. 2365 2366 Stile letterario • Ogni parola è separata da un solo spazio. Tipograficamente, lo spazio è una separazione di ampiezza non definita, spesso ampliato o compresso, per ottenere un allineamento del testo sia a sinistra che a destra. Un autore non deve pensare a queste cose quando scrive la propria opera; si deve limitare a spaziare le parole con un solo carattere spazio.3 La dattilografia insegnava a ottenere testi allineati a sinistra e a destra con l’inserzione opportuna di spazi aggiuntivi, vicino alle parole composte da poche lettere (congiunzioni, articoli, ecc.). Questo tipo di tecnica è ormai da abbandonare, lasciando semmai che siano i programmi di composizione a prendersi cura di questi problemi, anche quando il risultato finale deve essere un file di testo puro e semplice. I programmi di composizione più evoluti facilitano il compito dello scrittore eliminando gli spazi superflui, per cui con questi non c’è l’esigenza di porre attenzione alla dimensione delle spaziature.4 • I simboli di punteggiatura normale sono attaccati alla parola che precede e separati con uno spazio dalla parola che segue. Si tratta di: punto, virgola, due punti, punto e virgola, punto interrogativo e punto esclamativo. Alle volte, l’autore di documenti tecnici di informatica si lascia confondere dall’uso che si fa di tali simboli in un particolare linguaggio di programmazione o in altri ambiti analoghi. È chiaro, per esempio, che se si deve indicare un’estensione di un file, come «.sgml», non si può rispettare tale regola, ma il punto che precede quell’estensione non rappresenta un simbolo di punteggiatura del testo. • Le parentesi sono attaccate al testo che racchiudono e, rispetto alla punteggiatura esterna, si comportano come un’unica parola. La parentesi di apertura è separata con uno spazio dalla parola che precede, mentre quella di chiusura è separata con uno spazio dalla parola che segue. I simboli di punteggiatura normale che dovessero seguire una parentesi chiusa vanno attaccati a questa ultima. Nella lingua italiana non è consentito racchiudere all’interno di parentesi un periodo terminante con il punto fermo. Questa modalità è tipica della lingua inglese e i traduttori devono tenerne conto, al limite togliendo le parentesi nella frase tradotta. • Il testo riportato tra virgolette si comporta come quello racchiuso tra parentesi. La lingua italiana prevede l’uso di virgolette uncinate (in basso), virgolette elevate doppie e singole. Secondo la grammatica, le virgolette uncinate, o virgolette basse, sono da preferire. Tuttavia, dal momento che le virgolette elevate possono essere ottenute anche utilizzando soltanto il codice ASCII tradizionale a 7 bit, molti autori preferiscono accontentarsi e utilizzare solo quelle elevate.5 • Il trattino di unione è corto e unito alle parole da collegare. Si usa per unire insieme due parole in modo da formare una parola composta. I programmi di composizione tendono a considerare un trattino singolo come un trattino corto, proprio per questo scopo. 3 Secondo una regola della tipografia del passato, ormai condannata generalmente, era necessario aumentare lo spazio che divide la fine di un periodo dall’inizio del successivo. Per qualche ragione si trovano ancora documenti in lingua inglese che seguono questa regola, anche quando si tratta di file di testo. 4 Purtroppo LaTeX segue la vecchia regola dell’allungamento dello spazio dopo il punto fermo che chiude il periodo, con l’aggravante che per riuscire a determinarlo può fare solo delle supposizioni, che a volte sono errate. Per fare in modo che LaTeX eviti di applicare questa regola errata, si può utilizzare il comando ‘\frenchspacing’ nel preambolo del documento. 5 Quando il sistema di composizione si basa su TeX e si usano virgolette elevate, le virgolette doppie si ottengono preferibilmente attraverso una coppia di apici singoli aperti (‘‘‘’) e una coppia di apici singoli chiusi (‘’’’). In altri casi, soprattutto quando si tratta di file di testo puri e semplici, gli apici doppi si indicano con le virgolette normali (‘"..."’). Stile letterario 2367 • La lineetta, o trattino lungo, serve per introdurre un discorso diretto, oppure un inciso. Il trattino utilizzato per delimitare un discorso diretto, viene usato normalmente solo in apertura. Può apparire anche un trattino in chiusura quando al discorso diretto segue un commento. Se il trattino si usa per delimitare un inciso, si usa per aprirlo e solitamente anche per chiuderlo, come se si trattasse di parentesi. Generalmente, il trattino lungo è preceduto e seguito da uno spazio; davanti al trattino di chiusura vanno collocati il punto interrogativo, il punto esclamativo e i puntini, mentre per gli altri simboli di punteggiatura non esiste una convenzione precisa.6 221.2.2 Utilizzo dei simboli di interpunzione L’uso della punteggiatura nella lingua italiana è definito da regole molto vaghe che si prestano a facili eccezioni di ogni tipo. Qui si elencano solo alcuni concetti fondamentali. • , La virgola è un segno di interpunzione che collega due segmenti di testo separati da un pausa debole. • ; Il punto e virgola è un segno di interpunzione che si colloca a metà strada tra la virgola e il punto. Non segna la chiusura di un periodo. • : I due punti sono un simbolo di interpunzione esplicativo. Collegano due segmenti di testo separati dal punto di vista sintattico, in cui la seconda parte, quella che segue il simbolo, elenca, chiarisce o dimostra il concetto espresso nella prima parte. • . Il punto fermo è un segno di interpunzione che collega due segmenti di testo separati da un pausa forte. Generalmente segna la conclusione di un periodo. La parola successiva al punto ha l’iniziale maiuscola. • ! Il punto esclamativo indica generalmente la conclusione di un’esclamazione affermativa. Generalmente, quando conclude un periodo, il testo che segue ha l’iniziale maiuscola. • ? Il punto di domanda indica un tono interrogativo alla fine di una frase. Generalmente, quando conclude un periodo, il testo che segue ha l’iniziale maiuscola. • ... I punti di sospensione sono in numero fisso di tre e indicano che il discorso non viene portato a conclusione. Generalmente, sono uniti alla parola o al segno di interpunzione che li precede, oppure distanziati, a seconda che siano solo una sospensione oppure indichino l’omissione di un nome o di un’altra parola. Se si trovano alla fine di un periodo, dove andrebbe collocato un punto, questo non viene aggiunto e la frase successiva inizia con la maiuscola. Nello stesso modo, se si trovano alla fine di un’abbreviazione che termina con un punto, questo punto viene assorbito. 6 TeX permette l’uso di tre trattini di lunghezza differente: il trattino corto che si ottiene con un trattino singolo, il trattino medio che si ottiene con due trattini in sequenza e il trattino lungo che si ottiene con tre. Nella lingua italiana vanno usati solo i primi due, dove il trattino medio di TeX corrisponde al trattino lungo della nostra grammatica. Stile letterario 2368 • ecc. Il punto di abbreviazione, quando si trova alla fine di un periodo, conclude da solo anche il periodo stesso, ed è seguito da iniziale maiuscola. • ( ) Le parentesi, generalmente tonde, servono per delimitare un inciso, come un commento, una nota dello scrivente, un chiarimento, ecc. Generalmente, i commenti del redattore o del traduttore sono terminati, entro l’ambito delle parentesi, con le sigle NdR (nota del redattore) e NdT (nota del traduttore). 221.2.3 Accenti e troncamenti Nella lingua italiana scritta, l’uso degli accenti è un fatto puramente convenzionale. Ciò significa che l’accento non indica necessariamente il suono che ha effettivamente la lettera accentata, ma solo la sua rappresentazione consueta (più avanti, nella sezione 221.2.4 è riportato il testo originale della norma UNI 6015 sul «segnaccento obbligatorio»).7 • Nella lingua scritta è prevista (ed è obbligatoria) solo l’accentazione delle vocali finali delle parole nelle quali il tono della voce si rafforza sull’ultima sillaba (accento grafico). È possibile l’uso dell’accento per le vocali interne quando ciò serva per togliere ambiguità tra termini omografi (scritti nello stesso modo) che abbiano significati differenti. Generalmente, questa ambiguità è risolta dal contesto e raramente si incontra la necessità di utilizzare accenti interni. • Si utilizza comunemente solo l’accento grave (àèìòù), con l’eccezione della vocale «e» che può avere l’accento acuto (é). • Vogliono l’accento acuto le parole terminanti in ché (perché, poiché, ecc.), oltre a né (congiunzione) e sé (pronome tonico). In particolare, sé viene scritto generalmente senza accento quando è seguito da stesso, anche se la grammatica non lo richiede. • Vogliono l’accento alcuni monosillabi contenenti due vocali: ciò, già, giù, più e può. • Vogliono l’accento i monosillabi che senza potrebbero avere un significato differente. La tabella 221.1 mostra l’elenco dei monosillabi accentati più importanti. • Non vogliono l’accento alcuni monosillabi tra cui: qui, qua, sto e sta. • Solo alcune parole tronche richiedono la segnalazione di tale troncamento con l’apostrofo finale. In particolare: po’ (poco), mo’ (modo), ca’ (casa) e alcuni imperativi. • L’accento circonflesso (^) non si usa più. Serviva per i nomi terminanti in -io che al plurale terminerebbero in -ii (per esempio: armadio, armadii). Attualmente, si tende a usare questi plurali con una sola -i finale, a parte i casi in cui ciò genera ambiguità (assassino, assasini; assassinio, assassinii). 7 Nell’ambito della documentazione tecnica, sarebbe consigliabile di evitare l’uso di accentazioni non comuni, anche se queste potrebbero essere preferibili in ambienti più raffinati. Stile letterario 2369 Tabella 221.1. Elenco dei monosillabi accentati più importanti e dei loro equivalenti (omografi) non accentati. dà è là lì né sé sì indicativo di dare (dà valore) verbo avverbio (resta là) avverbio (vado lì) congiunzione (né questo né quello) pronome tonico (pieno di sé) avverbio (dice di sì) da e la li ne se si preposizione (da voi) congiunzione articolo pronome pronome (ne voglio ancora) pronome atono o congiunzione pronome Alle volte, l’uso delle vocali accentate può creare problemi tecnici, dovuti alla loro mancanza nell’insieme di caratteri a disposizione. In Italia, come nei paesi dell’Europa centrale, si utilizza la codifica ISO 8859-1 (Latin 1) che contiene tutte le nostre lettere accentate. Nelle circostanze in cui ciò non è attuabile (per esempio quando si dispone di un sistema configurato male, o la tastiera non dispone dei simboli necessari), occorre utilizzare delle tecniche di rappresentazione che dipendono dal programma utilizzato per la composizione. 221.2.3.1 SGML e XML SGML e XML, comprendendo in queste categorie anche HTML e XHTML, dispongono di una serie di entità standard, a cui corrispondono in particolare le macro elencate nella tabella 221.2. Tabella 221.2. Vocali accentate attraverso l’uso di macro SGML e XML. Vocale accentata à, À è, È ì, Ì ò, Ò ù, Ù é, É Macro corrispondente à, À è, È ì, Ì ò, Ò ù, Ù é, É 221.2.3.2 TeX/LaTeX TeX (e di conseguenza LaTeX) dispone di una serie di codici elencati nella tabella 221.3. Tabella 221.3. Vocali accentate per TeX. Vocale accentata à, À è, È ì, Ì ò, Ò ù, Ù é, É Codice TeX corrispondente \‘a, \‘A \‘e, \‘E \‘{\i}, \‘I \‘o, \‘O \‘u, \‘U \’e, \’E Stile letterario 2370 221.2.3.3 Lout Lout dispone del comando ‘@Char’ per indicare simbolicamente i segni tipografici che per qualche ragione non possono essere scritti letteralmente attraverso la codifica a disposizione. La tabella 221.4 mostra i comandi necessari a ottenere le vocali accentate. Tabella 221.4. Vocali accentate per Lout. Vocale accentata à, À è, È ì, Ì ò, Ò ù, Ù é, É Comando di Lout @Char agrave, @Char Agrave @Char egrave, @Char Egrave @Char igrave, @Char Igrave @Char ograve, @Char Ograve @Char ugrave, @Char Ugrave @Char eacute, @Char Eacute 221.2.3.4 Testo puro Quando si scrive un file di testo puro e semplice, ma non è possibile utilizzare la codifica ISO 8859-1, si può aggiungere un apice opportuno subito dopo la vocale da accentare. Naturalmente questa tecnica può valere solo per la lingua italiana in cui gli accenti si pongono solo nelle vocali finali. Visivamente il risultato è molto simile a quello corretto. Tabella 221.5. Trucco per rappresentare le vocali accentate quando non si può fare altrimenti. Vocale accentata à, À è, È ì, Ì ò, Ò ù, Ù é, É Vocale apostrofata corrispondente a‘, A‘ e‘, E‘ i‘, I‘ o‘, O‘ u‘, U‘ e’, E’ 221.2.4 Segnaccento obbligatorio (UNI 6015) Quello che segue è la norma UNI 6015 sull’uso degli accenti. Il testo è stato ottenuto da Scienza, tecnologia e arte della stampa e della comunicazione, Preparazione del manoscritto <http:// www.apenet.it/grafica/libri/Grafica/Grafica01/1206.html>. Segnaccento obbligatorio nell’ortografia della lingua italiana (Uni 601567): 1. Scopo La presente unificazione ha lo scopo di stabilire le regole ortografiche per il segnaccento nei testi stampati in lingua italiana, quando esso sia obbligatorio. 2. Definizione 2.1 Il segnaccento (o segno d’accento, o accento scritto) serve a indicare esplicitamente la vocale tonica, per esempio: andrà, colpì, temé, virtù. 2.2. Il segnaccento può essere grave (‘‘’) o acuto (‘’’). 3. Uso Stile letterario 2371 Il segnaccento è obbligatorio nei casi seguenti: 3.1. Su alcuni monosillabi, per distinguerli da altri monosillabi che si scrivono con le stesse lettere ma senza accento: ché («poiché», congiunzione causale) per distinguerlo da che (congiunzione in ogni altro senso, o pronome); dà (indicativo presente di dare) per distinguerlo da da (preposizione) e da’ (imperativo di dare); dì («giorno») per distinguerlo da di (preposizione) e di’ (imperativo di dire); è (verbo) per distinguerlo da e (congiunzione); là (avverbio) per distinguerlo da la (articolo, pronome, nota musicale); lì (avverbio) per distinguerlo da li (articolo, pronome); né (congiunzione) per distinguerlo da ne (pronome, avverbio); sé (pronome tonico) per distinguerlo da se (congiunzione, pronome atono); sì («così», o affermazione) per distinguerlo da si (pronome, nota musicale); té (pianta, bevanda) per distinguerlo da te (pronome). 3.2. Sui monosillabi: chiù, ciò, diè, fé, già, giù, piè, più, può, scià. 3.3. Su tutte le parole polisillabe su cui la posa della voce cade sulla vocale che è alla fine della parola, per esempio: pietà, lunedì, farò, autogrù. 4. Forma 4.1. Il segnaccento, nei casi in cui è obbligatorio, è sempre grave sulle vocali: a, i, o, u. 4.2. Sulla e, il segnaccento obbligatorio è grave se la vocale è aperta, è acuto se la vocale è chiusa: - è sempre grave sulle parole seguenti: ahimè e ohimè, caffè, canapè, cioè, coccodè, diè e gilè, lacchè, piè, tè; inoltre sulla maggior parte dei francesismi adattati, come bebè, cabarè, purè, ecc. e sulla maggior parte dei nomi propri, come Giosuè, Mosè, Noè, Salomè, Tigrè; - è acuto sulle parole seguenti: ché («poiché») e i composti di che (affinché, macché, perché, ecc.), fé e i composti affé, autodafé, i composti di re e di tre (viceré, ventitré), i passati remoti (credé, temé, ecc., escluso diè), le parole mercé, né, scimpanzé, sé, testé. 4.3. Anche per la o si possono distinguere i due timbri (aperto o chiuso) con i due accenti (grave ed acuto) ma solo in casi in cui l’accento è facoltativo, per esempio: còlto (participio passato di cogliere, e cólto («istruito»). 221.2.5 Uso della «d» eufonica Le congiunzioni e, o e la preposizione a, consentono l’aggiunta di una d eufonica, per facilitarne la pronuncia quando la parola che segue inizia per vocale. Si tratta di una possibilità e non di una regola; di questa d si potrebbe benissimo fare a meno. Ognuno tende a usare questa d eufonica in modo differente, a seconda della propria cadenza personale, che ne può richiedere o meno la presenza. Quando si scrive, bisognerebbe mantenere lo stesso stile, anche sotto questo aspetto, quindi ognuno deve stabilire e seguire un proprio modo. 2372 Stile letterario Esiste tuttavia un suggerimento che punta all’uso moderato di queste d eufoniche: usare la d solo quando la vocale iniziale della parola successiva è la stessa; e non usarla nemmeno quando, pur essendoci la stessa vocale iniziale nella parola successiva, ci sia subito dopo una d che possa complicare la pronuncia. 221.2.6 Elisione davanti alla lettera «h» In linea di massima, l’articolo che si mette davanti a un termine che inizia con la lettera h, è quello che si userebbe pronunciando quella parola come se iniziasse per vocale. Secondo questo principio, va usata l’elisione, così come si fa con i termini che iniziano per vocale, senza alcuna «h» anteriore. Per esempio: l’harem; l’hotel; l’host. Tuttavia, quando si tratta di un termine che, proveniendo da un’altra lingua, non è ancora diventato di uso comune e nella lingua originale si pronuncia con la lettera «h» iniziale aspirata, si preferisce evitare l’elisione. 221.2.7 Uso delle maiuscole L’iniziale maiuscola si utilizza all’inizio del periodo e per evidenziare i nomi propri. Nel dubbio è meglio evitare di utilizzare le maiuscole. La lingua italiana fa un uso diverso delle maiuscole rispetto ad altre lingue. Il novello scrittore di documenti tecnici tende a lasciarsi influenzare dall’uso che si fa delle maiuscole nella lingua inglese. Per questo è bene ribadire che in italiano l’uso di queste deve essere ridotto al minimo indispensabile. 221.2.8 Plurali Ci sono alcuni aspetti del plurale nella lingua italiana che vale la pena di annotare. In particolare, nel caso di chi deve utilizzare anche termini stranieri, si pone il problema di decidere se questi siano invariabili o meno. A questo proposito, esistono due regolette semplici e pratiche: • le parole terminanti per consonante sono invariate al plurale; • i termini di provenienza straniera non ancora assimilati sono invariati al plurale. In particolare, per quanto riguarda la seconda, la logica è che non si può applicare un plurale secondo le regole di una lingua straniera mentre si usa l’italiano. Inoltre, dato che nella maggior parte dei casi si tratta di termini inglesi, che nella loro lingua prenderebbero quasi sempre una terminazione in -s al plurale, diventerebbe anche difficile la loro pronuncia in italiano. 221.2.8.1 Interfacce o interfaccie? Esiste una regoletta che permette di stabilire facilmente come debba essere ottenuto il plurale delle parole che terminano in -cia e -gia: la i rimane se la c e la g sono precedute da vocale, oppure se la i viene pronunciata con accento, mentre viene eliminata se queste consonanti sono precedute da un’altra consonante. Quindi si ha: camicia, camicie e interfaccia, interfacce; ciliegia, ciliegie e spiaggia, spiagge; energia, energie. Stile letterario 2373 221.2.9 Elenchi Gli elementi puntati, o numerati, possono essere composti da elementi brevi, oppure da interi periodi. Se tutti gli elementi sono brevi: • l’elenco deve essere introdotto da una frase terminante con due punti; • ogni elemento deve essere terminato con un punto e virgola, a eccezione dell’ultimo che termina normalmente con un punto. La descrizione appena fatta mostra un esempio di elenco del genere. Se anche uno solo degli elementi è troppo lungo, è bene trasformare tutti gli elementi in periodi terminati da un punto. In tal caso, se l’elenco viene introdotto da una frase, anch’essa termina con un punto. Ci possono essere situazioni in cui queste indicazioni non sono applicabili: come sempre è necessario affidarsi al buon senso. 221.2.10 Citazioni Le citazioni, cioè le frasi o i brani riprodotti letteralmente da altri documenti, devono apparire distinte chiaramente dal testo normale. Si usano normalmente queste convenzioni: • quando la citazione è incorporata nel testo viene delimitata attraverso le virgolette, oppure utilizzando il corsivo se la citazione è particolarmente breve; • le citazioni incluse in un’altra citazione già virgolettata si evidenziano attraverso l’uso di un altro tipo di virgolette, cominciando da quelle uncinate («»), utilizzando poi quelle elevate doppie (‘‘’’) e terminando con quelle singole (‘’); • quando la citazione è molto lunga e occupa diversi capoversi, conviene utilizzare un corpo minore o un altro espediente tipografico per distinguerla dal testo normale, come con l’uso di rientri differenti; • quando la citazione è lunga e non si vogliono utilizzare altri espedienti per evidenziarla, si utilizzano le virgolette, ripetendo quelle di apertura all’inizio di ogni capoverso; • all’interno delle citazioni possono apparire dei commenti o chiarimenti inseriti da chi scrive, delimitandoli attraverso l’uso di parentesi quadre; • all’interno delle citazioni vanno indicate le omissioni, che possono essere segnalate attraverso l’uso dei puntini di sospensione racchiusi tra parentesi quadre (come per i commenti); • quando si fanno delle omissioni nella citazione all’inizio o alla fine del brano, è preferibile l’uso dei puntini di sospensione senza che questi siano racchiusi tra parentesi quadre; all’inizio i puntini di sospensione sono staccati dalla prima parola, mentre alla fine sono attaccati all’ultima. Stile letterario 2374 221.3 Traduzioni e termini stranieri Le traduzioni rappresentano un problema in più, dal punto di vista dell’uniformità stilistica espressiva, soprattutto perché sono frequentemente il risultato di un lavoro di gruppo. Il problema più grave è rappresentato dalla traduzione o dall’acquisizione di quei termini che non fanno parte del linguaggio comune. • Una traduzione non può essere letterale, perché lingue diverse hanno strutture differenti e il significato che si attribuisce alle parole dipende dal contesto. Quello che conta, quindi, è che il significato sia mantenuto. • Quando si tratta di termini tecnici di origine straniera, la loro traduzione può essere inopportuna, soprattutto quando chi deve esprimersi con quei concetti utilizza già abitualmente il termine in questione, nella forma originale, senza tradurlo. In pratica, è importante che gli utenti esperti possano trovare familiare la traduzione di un documento tecnico rivolto a loro. • Una traduzione utilizzata largamente sul campo deve essere privilegiata al momento della scelta. È importante evitare che gli utenti esperti possano essere confusi da una traduzione. In pratica: gli utenti esperti devono trovare familiari le traduzioni scelte. • Quando un termine straniero ha un significato più specifico della sua traduzione letterale, allora non conviene tradurlo. L’esempio più importante che deriva da questa affermazione è il termine file, che in italiano identifica precisamente il concetto di archivio elettronico generico . L’attività di traduzione è tanto più delicata se si considerano i vincoli posti dalle convenzioni internazionali che regolano l’editoria. In breve, la traduzione deve essere autorizzata dall’autore originale, verso il quale ci si assume la responsabilità del buon esito di questa operazione. Per questo, la traduzione non può alterare il contenuto espresso dall’autore originale e nemmeno chiarirlo. Nello stesso modo, una traduzione deve sempre essere accompagnata dall’indicazione dei nomi dei traduttori che l’hanno realizzata. 221.3.1 Acquisizione di termini inglesi Quando si decide di lasciare inalterato il termine straniero nel testo italiano, si pone il problema di stabilire il modo con cui questo possa convivere con il resto del testo. L’unica regola sicura è la verifica dell’uso generale, attraverso la discussione nelle liste specializzate. Tuttavia si possono definire alcune regole di massima, per dare l’idea del problema. È importante osservare che nell’ambito delle traduzioni di documenti tecnici, nella stragrande maggioranza dei casi, si ha a che fare con l’inglese. Infatti, l’acquisizione di un termine straniero tende a seguire logiche differenti a seconda della lingua di origine. Per comprenderlo basta pensare con quanta facilità si potrebbe acquisire un termine francese, come «console», rispetto a un termine inglese. • La prima cosa da fare di fronte a un termine da non tradurre è di verificare in un vocabolario di lingua italiana; se c’è, il problema è risolto. Questo potrebbe sembrare un consiglio banale; ma attualmente appaiono già parole come «input» e «output» che non sono poi di uso così generalizzato. Stile letterario 2375 • Un termine inglese può assumere il genere che avrebbe se tradotto in italiano, oppure quello che suona meglio dandogli un significato italiano. In caso di dubbio è importante controllare l’uso comune (se esiste). • I termini inglesi non tradotti sono invariabili al plurale, cioè quando sono inseriti in testi in italiano vanno scritti sempre al singolare, senza aggiungere la lettera «s» finale, anche se ci si riferisce a una quantità maggiore di uno. A titolo di esempio si pensi al termine «mouse» che al plurale inglese diventa «mice». Chi usa questo termine, probabilmente è costretto a farlo, dato che l’italiano offre poche alternative; forse si potrebbe indicare come «dispositivo di puntamento», ma questa definizione è troppo generica e probabilmente non verrebbe compresa. Pertanto, chi usa questi termini non può essere anche costretto a conoscere perfettamente l’inglese e il modo corretto di usare i plurali in quella lingua. In altri termini, la lingua italiana non può incorporare le regole di un’altra lingua. Quando il termine che non si traduce non è di uso comune nell’ambiente a cui si rivolge il documento, dovrebbe essere evidenziato in corsivo tutte le volte che viene utilizzato. Per chiarire meglio il concetto, un termine tecnico può essere o meno di uso comune per il pubblico di lettori a cui si rivolge: se si tratta di un termine considerato normale per quell’ambiente, non è il caso di usare alcuna evidenziazione. 221.3.2 Stesura di un glossario Quando si traduce un documento è importante la preparazione di un glossario, inteso come una raccolta di traduzioni standard che permettono di mantenere uniformità nel documento tradotto. Questo diventa tanto più importante quando si lavora in gruppo, o si partecipa alla traduzione di un gruppo di opere che fanno parte di uno stesso ambito tecnico. Un glossario del genere non può essere un documento statico, in quanto si ha la necessità di aggiornare continuamente il suo contenuto; se non altro per estenderlo. Nell’ambito della documentazione GNU, ci si può iscrivere alla lista [email protected] per chiedere informazioni sul lavoro già svolto e per discutere termini non ancora definiti dal glossario in corso di realizzazione. Per iscriversi basta inviare un messaggio a [email protected] contenente nel corpo (e non nell’oggetto) il testo seguente: ‘subscribe it’ L’invio di messaggi al gruppo di discussione va indirizzato poi a [email protected]. Eventualmente si può scaricare il glossario attuale da <ftp://ftp.linux.it/pub/People/md/glossario.tgz>, tenendo presente che il moderatore della lista desidera che non sia distribuito ulteriormente, in modo da evitare che si diffondano versioni obsolete. Come ultima nota è opportuno chiarire che un glossario per la traduzione può essere solo uno strumento, per l’utilizzo da parte di persone in grado di capire il contesto in cui i termini sono usati e di stabilire se le voci corrispondenti del glossario sono applicabili alle situazioni particolari. Stile letterario 2376 221.3.3 Opere originali Anche l’autore di un’opera originale di carattere tecnico, si imbatte in problemi simili a quelli dei traduttori. Infatti, quando l’acquisizione di un termine tecnico straniero riguarda solo l’ambito specializzato per il quale si scrive, si può dubitare del modo giusto di utilizzarlo. Per questo, anche gli autori di opere originali possono avere la necessità di preparare un glossario e di discutere le espressioni migliori per un concetto determinato. 221.4 Strafalcioni comuni L’influenza della lingua inglese porta a deformazioni sempre più frequenti nella lingua italiana. Queste annotazioni vogliono essere di aiuto a chi scrive in italiano sotto l’influenza della prosa inglese, sia perché sta traducendo, sia perché è abituato a leggere solo documentazione tecnica scritta in inglese. Il problema più evidente, ma più facile da affrontare, è quello dei «falsi amici»: quei termini che, pur assomigliandosi (e pur avendo, spesso, la stessa etimologia), hanno significati diversi nelle due lingue. Gli esempi più celebri sono «factory» che diventa erroneamente «fattoria» e «cold» che si trasforma in «caldo». Il problema meno evidente e per questo più insidioso è dato dalle altre differenze fra le due lingue: la punteggiatura, l’uso delle maiuscole e la struttura delle frasi. Trascurando queste particolarità si rischia di ottenere un testo che è formalmente in italiano, ma che non «suona» come tale. Per completare il quadro, viene mostrato qualche esempio comune per chiarire questi concetti, ma è bene ricordare che le possibilità sono infinite e che l’unico modo per scrivere in buon italiano è leggere tanto buon italiano (così come avviene per qualsiasi linguaggio di programmazione). 221.4.1 Falsi amici I «falsi amici» sono quei termini inglesi che sembrano avere una traduzione ovvia in italiano, che però non è corretta. Lo specchietto che si vede nella tabella 221.6 mostra la traduzione corretta di alcuni termini, frequenti nei testi informatici, lasciando intuire l’errore comune che si fa al riguardo. Tabella 221.6 Traduzioni corrette dei «falsi amici». consistent exhaustive line re... (recursive) set to set subject to process to assume proper (agg.) proper (avv.) to support to return something coerente esauriente riga (quasi sempre) ri... (ricorsivo) insieme («set» è tennistico) impostare («settare» è di pessimo gusto) oggetto (di una lettera o di un messaggio) elaborare supporre giusto, corretto vero e proprio si usi, per quanto possibile, una perifrasi restituire qualcosa («ritornare» è intransitivo) Stile letterario 2377 221.4.2 Ortografia e sintassi Quello che segue è un elenco di annotazioni riguardo all’uso dell’ortografia e della sintassi. • La «e» o la «o» che introduce l’ultimo termine di un elenco non va preceduta da virgola. In inglese americano la norma è di usare la virgola (ma gli inglesi non la usano); a volte in italiano la virgola è ammissibile, ma si tratta di eccezioni. • Se le frasi sono negative, allora devono essere separate con «né». Per esempio: File che hanno questo bit settato non possono essere cancellati con DEL o modificati. va sostituito con: I file che hanno questo bit impostato non possono essere cancellati con DEL né modificati. • I periodi italiani sono più complessi di quelli inglesi, a parità di registro. Come buona regola, metà dei punti fermi vanno sostituiti con congiunzioni, subordinate, due punti o punti e virgola. L’esempio seguente di traduzione viene da hostname(1). -F, --file filename Read the host name from the specified file. (lines starting with a ‘#’) are ignored. Comments -F, --file nomefile Legge il nome dell’host dal file specificato, ignorando i commenti (righe che iniziano con ‘#’). • L’uso del futuro in inglese è diverso da quello dell’italiano. L’esempio proviene da mpage(1). -O Print 2 normal pages per sheet. But, this option will print every first and forth page of every set of four pages. This option will ignore the -a and -l options. -O Stampa due pagine normali per foglio: questa opzione, però, stampa la prima e la quarta pagina per ogni dato insieme di quattro pagine. Questa opzione ignora le opzioni -a e -l. • I nomi dei mesi sono minuscoli. • I numeri piccoli vanno scritti preferibilmente per esteso. • In italiano si usa, di solito, la sequenza nome+aggettivo; il contrario, aggettivo+nome, per quanto accettabile, ha spesso un significato diverso. Per esempio, si osservi la differenza tra «pover’uomo» e «uomo povero». • Bisogna sempre concordare il genere grammaticale: «la directory padre» non ha senso. • Spesso chi scrive in inglese usa contorsioni grammaticali assurde per evitare di denotare il genere della terza persona singolare; in particolare, si può trovare «they» o «their» usati al singolare: ovviamente in italiano ciò non va fatto. L’esempio proviene da finger(1): Mail status is shown as ‘‘No Mail.’’ if there is no mail at all, ‘‘Mail last read DDD MMM ## HH:MM YYYY (TZ)’’ if the person has looked at their mailbox since new mail arriving, or ‘‘New mail received ...’’, ‘‘ Unread since ...’’ if they have new mail. Stile letterario 2378 221.5 Unità di misura Nella documentazione a carattere scientifico diventa fondamentale la coerenza e la precisione nel modo in cui si indicano le grandezze e le unità di misura, oltre che la scelta di queste. In generale, ogni ambiente tecnico particolare tende a utilizzare le proprie grandezze e le proprie unità di misura, tralasciando gli sforzi di standardizzazione internazionale, contribuendo così a complicare inutilmente il proprio settore. Purtroppo, l’ambito informatico costituisce l’esempio più problematico sotto questo aspetto, dal momento che l’esigenza di mantenere una compatibilità con il sistema binario ha attribuito a delle denominazioni ben precise del sistema decimale un significato differente rispetto a quello comune a tutti gli altri ambiti scientifici. Lo standard internazionale sulle unità di misura è costituito dal SI, ovvero Le Système international d’unités, in italiano Sistema internazionale di unità. Il punto di riferimento per questo lavoro di armonizzazione è il BIPM (Bureau international des poids et mesures), con sede in Francia (<http://www.bipm.fr/>). 221.5.1 Come si scrive una grandezza Per esprimere una quantità riferita a una grandezza in modo grafico, occorre disporre del simbolo (la sigla) che ne esprime l’unità di misura o un multiplo opportuno di tale unità, al quale si fa precedere il numero, in cifre, di tale quantità: n simbolo È importante che tra il numero e la sigla ci sia uno spazio, che non deve poter essere interrotto in fase di impaginazione del testo. Per esempio: si può scrivere 5 kg, ma non 5kg. 221.5.2 Nomi e simboli È bene chiarire il significato di alcuni termini che riguardano la misurazione di qualcosa: grandezza ciò che viene misurato, come la lunghezza, la massa8 , il tempo; unità di misura il nome attribuito a ciò che si usa per misurare, come il metro, il kilogrammo9 , il secondo; simbolo il simbolo che rappresenta l’unità di misura in modo standard, come «m», «kg», «s»; I nomi delle unità di misura si esprimono generalmente senza iniziale maiuscola, mentre i simboli usati per rappresentarle simbolicamente vanno espressi esattamente come stabilito dagli standard, per quanto riguarda l’uso delle lettere maiuscole o minuscole. 8 Secondo il SI, questa è la definizione corretta, mentre il «peso» è la forza applicata a un oggetto. Secondo il SI, questa è l’unità di misura della massa, tenendo conto che i prefissi si utilizzano facendo riferimento al grammo. 9 Stile letterario 2379 Tabella 221.7. Esempi di grandezze e unità di misura. Grandezza lunghezza massa tempo corrente elettrica Unità di misura metro kilogrammo secondo ampere Simbolo m kg s A 221.5.3 Prefissi moltiplicatori Oltre alla definizione dei simboli che esprimono le unità di misura, si aggiungono dei simboli che rappresentano un multiplo ben preciso di tali unità. Tali simboli di moltiplicazione si pongono davanti al simbolo di unità a cui si riferiscono; per esempio, il simbolo «km» rappresenta mille unità «m», ovvero mille volte il metro. I simboli che rappresentano tali moltiplicatori hanno anche un nome che normalmente si esprime senza iniziale maiuscola, indipendentemente dalla forma, maiuscola o minuscola, che ha il simbolo stesso. I moltiplicatori riferiti alle unità di misura hanno un significato e un valore ben preciso. È un errore l’uso dei termini «kilo», «mega», «giga» e «tera», per rappresentare moltiplicatori pari a 210, 220, 230 e 240, come si fa abitualmente per misurare grandezze riferite a bit o a byte. Tabella 221.8. Prefissi del Sistema internazionale di unità (SI). Nome yotta zetta exa peta tera giga mega kilo hecto, etto deca Simbolo Y Z E P T G M k h da deci centi milli micro nano pico femto atto zepto yocto d c m µ n p f a z y Valore 1024 1021 1018 1015 1012 109 106 103 102 10 1 10-1 10-2 10-3 10-6 10-9 10-12 10-15 10-18 10-21 10-24 Note Lettera «k» minuscola. Nessun moltiplicatore. Stile letterario 2380 221.5.4 Prefissi per multipli binari Lo standard IEC 60027-2 introduce un gruppo nuovo di prefissi da utilizzare in alternativa a quelli del SI, per risolvere il problema dell’ambiguità causata dall’uso improprio dei prefissi del SI in ambito informatico. A questo proposito, una discussione particolareggiata su questo argomento si può trovare nel documento Standardized Units for Use in Information Technology, di Markus Kuhn, <http://www.cl.cam.ac.uk/~mgk25/information-units.txt>. Tabella 221.9. Prefissi IEC 60027-2. Origine kilobinary megabinary gigabinary terabinary petabinary exabinary zettabinary yottabinary Nome kibi mebi gibi tebi pebi exbi zebi yobi Simbolo Ki Mi Gi Ti Pi Ei Zi Yi Valore 210 220 230 240 250 260 270 280 Note Si usa la «K» maiuscola. La tabella 221.9 riporta l’elenco di questi prefissi speciali. 221.6 Rappresentazione di valori La rappresentazione di valori numerici tende a seguire forme differenti a seconda del contesto e delle convenzioni nazionali. Nella Guide for the Use of the International Systems of Units (SI), pubblicato dal NIST (National institute of standards and technology), si trovano alcuni criteri per risolvere il problema in modo non ambiguo, validi anche al di fuori della realtà inglese. 221.6.1 Valori percentuali In generale, l’uso del simbolo ‘%’ va inteso come una forma abbreviata per 0,01 e in questo modo va usato, senza eccedere. In particolare, il simbolo di percentuale va posto dopo un valore numerico, staccato da questo, ma non separabile in fase di composizione tipografica: n % Per esempio, si può scrivere ‘x = 0,025 = 2,5 %’, mentre non è corretta la forma ‘x = 0,025 = 2,5%’. 221.6.2 Valori numerici Nella lingua italiana, come in molte altre, si usa la virgola come segno di separazione tra la parte intera e quella decimale, mentre nei paesi di lingua inglese, si utilizza il punto. A parte il problema di scegliere il segno opportuno in base alle proprie convenzioni nazionali, si pone piuttosto la difficoltà nel rappresentare numeri composti da un grande numero di cifre. La Guide for the Use of the International Systems of Units (SI) indica un metodo molto semplice e non equivoco: si separano le cifre a gruppi di tre, usando semplicemente uno spazio, sia prima che dopo il marcatore decimale, come si vede in questi esempi: 123 456 789 3 456 789,012 345 6 6 789,012 3 Stile letterario 2381 Naturalmente, lo spazio in questione non può consentire l’interruzione della riga in fase di composizione. È ammissibile anche un’eccezione in presenza di raggruppamenti di sole quattro cifre, prima o dopo il marcatore decimale. In quel caso si può evitare la separazione: 1234 23,2345 Un altro problema è quello della rappresentazione di valori numerici espressi con una base maggiore di 10, per i quali si utilizzano le prime 10 cifre numeriche e per il resto si usano le lettere alfabetiche. Queste lettere andrebbero utilizzate coerentemente, possibilmente in forma maiuscola. 221.7 Stile tipografico La definizione dello stile tipografico è un altro punto delicato nella definizione dello stile letterario generale. Di solito, la sua preparazione, è compito del tipografo o del coordinatore di un gruppo di autori o traduttori. Il modo migliore per stabilire e utilizzare uno stile tipografico è quello di usare un sistema SGML, attraverso cui definire un DTD che non permetta alcun dubbio nella relazione che ci deve essere tra le varie componenti di un documento. In questo modo, gli autori hanno solo il compito di qualificare correttamente le varie componenti del testo, senza pensare al risultato finale, per modificare il quale si può semmai intervenire sul sistema di conversione successivo. Le sezioni seguenti trattano dei problemi legati alla definizione di uno stile tipografico per la redazione di documenti tecnico-informatici, mostrando prevalentemente esempi in SGMLtoolsLinuxDoc e a volte anche in LaTeX. L’idea è presa dalla guida di stile del gruppo di documentazione di Linux: LDP (Linux documentation project), ma le indicazioni si basano sulle consuetudini tipografiche italiane. 221.7.1 Blocchi di testo Scrivendo documenti che riguardano l’uso dell’elaboratore, si incorre frequentemente nella necessità di scrivere nomi, o intere parti di testo, che devono essere trattati in modo letterale. Possono essere nomi di file e directory, comandi, porzioni del contenuto di file, listati di programmi, ecc. In questi casi è sconsigliabile l’uso di un tipo di carattere proporzionale, perché si rischierebbe di perdere delle informazioni importanti. Si pensi al trattino utilizzato nelle opzioni della maggior parte dei comandi Unix: utilizzando un carattere proporzionale, attraverso un sistema di composizione come LaTeX, si otterrebbe un trattino corto, mentre due trattini posti di seguito genererebbero un trattino normale; e ancora, da tre trattini si otterrebbe un trattino largo. Altri tipi di problemi sono dati da nomi di altro genere, come i marchi di fabbrica, e dalla necessità di marcare dei concetti quando appaiono per la prima volta. 221.7.1.1 Nomi di file e directory • I nomi di file, di qualunque tipo, dovrebbero essere rappresentati attraverso un tipo di carattere a spaziatura fissa. • I nomi di questi tipi di entità sono sensibili alla differenza tra maiuscole e minuscole. Per questo vanno scritti sempre così come sono, anche quando si trovano all’inizio di un periodo, senza acquisire un’eventuale iniziale maiuscola. 2382 Stile letterario • I nomi di file eseguibili, in quanto tali, sono indicati preferibilmente senza il percorso necessario al loro avvio. • I nomi di programmi per i sistemi Dos dovrebbero essere indicati utilizzando lettere maiuscole, senza tralasciare l’estensione. 221.7.1.2 Schermate, listati e simili Il testo ottenuto da listati di vario tipo, come i pezzi di un programma sorgente, il risultato dell’elaborazione di un comando, o il contenuto di una schermata, possono essere rappresentati convenientemente attraverso un ambiente di inclusione di testo letterale a spaziatura fissa. Generalmente, con LinuxDoc si utilizza l’ambiente ‘verb’ contenuto in ‘tscreen’ (l’uso dell’ambiente ‘code’ è sconsigliabile). Il problema sta nel fatto che l’ampiezza di tale testo non può superare i margini del corpo del documento, in base al tipo di impaginazione finale che si ritiene dover applicare. Infatti, tale testo non può essere continuato nella riga successiva perché ciò costituirebbe un’alterazione delle informazioni che si vogliono mostrare. Generalmente, non è possibile superare un’ampiezza di 80 colonne, pari a quella di uno schermo a caratteri normale. 221.7.1.3 Variabili di ambiente • I nomi di variabili di ambiente dovrebbero essere rappresentati attraverso un tipo di carattere a spaziatura fissa. • I nomi di questi tipi di entità sono sensibili alla differenza tra maiuscole e minuscole. Per questo vanno scritti sempre così come sono, anche quando si trovano all’inizio o all’interno di un periodo. • A seconda del tipo di documentazione, potrebbe essere stata definita la convenzione per cui queste debbano essere indicate sempre precedute dal simbolo dollaro (‘$’). La scelta di rappresentare le variabili utilizzando il dollaro come prefisso è motivata dalla facilità con cui questa può essere identificata durante la lettura del testo. Tuttavia, questa scelta potrebbe essere discutibile, perché il dollaro non appartiene al nome della variabile e perché potrebbe indurre il lettore a utilizzarlo sempre, anche quando negli script non si deve. Quindi, il buon senso deve guidare nella decisione finale. 221.7.1.4 Comandi e istruzioni A volte si ha la necessità di indicare un comando, o un’istruzione, all’interno del testo normale. Per questo, è opportuno utilizzare un carattere a spaziatura fissa, come nel caso dei nomi di file e directory, però qui si pone un problema nuovo dovuto alla possibile presenza di spazi e trattini. I programmi di composizione normali tendono a interrompere le righe, quando necessario, in corrispondenza degli spazi ed eventualmente anche dei trattini. Se il comando o l’istruzione che si scrive è breve, è consigliabile l’utilizzo di spazi e trattini non interrompibili.10 Quando si utilizza SGML (compreso HTML), si può usare l’entità ‘ ’ per indicare uno spazio non interrompibile, mentre se si usa solo LaTeX, è il carattere tilde (‘~’) che ha questa funzione. 10 Naturalmente questo ha senso se poi il programma di composizione non tenta di suddividere le parole in sillabe. Stile letterario 2383 Il problema del trattino non è semplice, perché non esiste un trattino generico non separabile, fine a se stesso. Di trattini ne esistono di varie misure e non sempre esistono corrispondenti per diversi tipi di programmi di composizione. 221.7.1.5 Nomi di applicativi Quando si fa riferimento al nome di un programma si pongono due alternative: l’indicazione del file eseguibile oppure del nome attribuito dall’autore al suo applicativo. Per comprendere la differenza, si può pensare a Apache: il servente HTTP. Non si tratta di un semplice eseguibile, ma di un applicativo composto da diverse parti, in cui l’eseguibile è ‘httpd’. Nello stesso modo, nel caso di Perl (il linguaggio di programmazione), si può pensare all’applicativo in generale, composto dalle librerie e tutto ciò che serve al suo funzionamento; oppure si può voler fare riferimento solo all’eseguibile: ‘perl’. • I nomi di programmi applicativi dovrebbero essere indicati nello stesso modo in cui lo fa il loro autore, rispettando l’uso delle maiuscole e delle minuscole, in qualunque posizione del testo. • I nomi di questi tipi di entità non dovrebbero essere evidenziati in modo particolare. Esempi Ghostscript è un programma molto importante. nanoBase è un semplice applicativo per Dos. 221.7.1.6 Concetti e termini nuovi • I concetti e i termini che non si ritengono familiari per il lettore, dovrebbero essere evidenziati la prima volta che si presentano. Per questo tipo di evidenziazione si utilizza un neretto oppure un corsivo. L’uso del neretto è contrario alla tradizione dei testi italiani, in cui questo viene fatto normalmente utilizzando solo il corsivo. Tuttavia, il neretto si presta meglio alla composizione in formati molto diversi; per esempio si ottiene facilmente anche su un documento da visualizzare attraverso uno schermo a caratteri. Esempi Questo meccanismo permette di inserire le cosiddette entità interne , con cui si possono definire delle macro. 221.7.1.7 Termini stranieri A volte è opportuno utilizzare termini stranieri, non tradotti. Quando si tratta di termini non ben acquisiti nel linguaggio comune, almeno per il pubblico a cui si rivolge il documento, è opportuno utilizzare il corsivo tutte le volte in cui il termine viene adoperato. Un termine tecnico può essere o meno di uso comune per il pubblico di lettori a cui si rivolge: se si tratta di un termine considerato normale per quell’ambiente, non è il caso di usare alcuna evidenziazione. Stile letterario 2384 221.7.1.8 Nomi proprietari e logotipi L’indicazione di nomi che fanno riferimento a marchi di fabbrica o simili, va fatta come appare nel copyright o nella nota che fa riferimento al brevetto, rispettando l’uso delle maiuscole e dell’eventuale punteggiatura. Si dovrebbe evitare, quindi, di prendere in considerazione un eventuale logo grafico del prodotto. Non è opportuno fare risaltare maggiormente i nomi di questo tipo.11 All’interno del testo non è conveniente fare riferimento al detentore del copyright o del brevetto. Eventualmente, di questo problema dovrebbero farsi carico delle note opportune all’inizio del documento che si scrive.12 Esempi Sistema di stampa PostScript... Scheda SCSI Adaptec... Unità magneto-ottica Fujitsu... Hewlett Packard 221.7.2 Titoli Nei testi di lingua italiana, i titoli vanno scritti come se si trattasse di testo normale, con le particolarità seguenti: • non viene mai posto il punto fermo finale; • si cerca di evitare l’inserzione di altri segni di punteggiatura, a meno che ciò sia necessario per qualche motivo; • non si usano evidenziazioni particolari di parole o nomi come invece potrebbe avvenire nel testo normale. Un documento a carattere tecnico viene normalmente suddiviso in segmenti a più livelli. Per avere maggiore facilità nella trasformazione del documento in diversi formati tipografici finali, conviene limitare la scomposizione a un massimo di due livelli. Nel caso di LinuxDoc, significa limitarsi a usare ‘sect’ e ‘sect1’. 221.7.2.1 Didascalie Gli elementi che non fanno parte del flusso normale di un documento, come tabelle e figure, sono accompagnate generalmente da un titolo e da una didascalia. Il titolo serve a identificarle, mentre la didascalia ne descrive il contenuto. I titoli di tabelle, figure e oggetti simili, seguono le regole dei titoli normali, mentre il testo delle didascalie segue le regole del testo normale. Tuttavia, quando si utilizzano programmi di composizione che permettono di abbinare solo una nota descrittiva, che funga sia da titolo che da didascalia, occorre fare una scelta: 11 A questa regola si può aggiungere che, nel caso il nome sia scritto utilizzando solo lettere maiuscole, può essere opportuno limitarsi a indicarlo utilizzando solo l’iniziale maiuscola, lasciando il resto in minuscolo. 12 In generale, non è indispensabile fare alcun tipo di riferimento di questo genere, se lo scopo di ciò che si scrive non è quello di trattare espressamente di questo o quel prodotto. Stile letterario 2385 • quando le note sono brevi, è opportuno che si comportino come i titoli, cioè non contengano simboli di punteggiatura; • quando sono più lunghe, si può decidere di trattarle come didascalie vere e proprie, con tutti i simboli di punteggiatura necessari per una comprensione corretta del contenuto. Naturalmente, la scelta fatta deve valere per tutte le descrizioni che si abbinano a questi oggetti di un particolare documento: brevi o lunghe che siano. 221.7.2.2 Elenchi descrittivi Gli elenchi descrittivi, come quelli che si ottengono con LinuxDoc utilizzando la struttura seguente, possono essere insidiosi, perché potrebbero tradursi in modo differente a seconda del tipo di programma di composizione utilizzato. <descrip> <tag>Primo elemento</tag> Descrizione del primo elemento,... Bla bla bla... </descrip> L’elemento descrittivo dell’elenco è in pratica un titolo che introduce una parte di testo generalmente rientrata. Sotto questo aspetto, la voce descrittiva segue le regole già viste per i titoli. Tuttavia, il problema sta nel fatto che si potrebbe essere indotti a riprendere un discorso lasciato in sospeso quando veniva introdotto l’elenco, come nell’esempio seguente: Bla bla bla bla... Primo elemento Descrizione del primo elemento,... Bla bla bla... Qui si riprende il discorso precedente all’elenco descrittivo. ... Infatti, l’utilizzo dei rientri fa percepire immediatamente la conclusione dell’elenco stesso. Quando si scrive un documento che deve poter essere convertito in molti formati differenti, che quindi potrebbe essere elaborato da programmi di composizione di vario tipo, può darsi che i rientri vengano perduti e gli elementi descrittivi dell’elenco appaiano come dei titoli veri e propri. Ma se ciò accade, quando si ricomincia «il discorso lasciato in sospeso», sembra che questo appartenga all’argomento dell’ultimo titolo apparso. Bla bla bla bla... Primo elemento Descrizione del primo elemento,... Bla bla bla... Qui si riprende il discorso precedente all’elenco descrittivo. ... Pertanto, se si vogliono utilizzare strutture di questo tipo, è consigliabile che appaiano alla fine di una sezione, quando quello che viene dopo è un titolo di una sezione o di qualcosa di simile. Stile letterario 2386 221.7.3 Richiami in nota I richiami in nota (le note a piè pagina e quelle alla fine del documento) sono composti con le stesse regole del testo normale. Quando il riferimento a una nota si trova alla fine di una parola cui segue un segno di interpunzione, è opportuno collocare tale riferimento dopo il simbolo di interpunzione stesso. 221.7.4 Indicizzazione La costruzione di un indice analitico deriva dall’inserzione di riferimenti all’interno del testo, attraverso istruzioni opportune definite dal tipo di programma usato per la composizione. Nel caso particolare di LinuxDoc si utilizzano gli ambienti ‘nidx’ e ‘ncdx’, che vengono poi gestiti solo nella composizione attraverso LaTeX e ignorati in tutti gli altri casi. ‘ncdx’ si usa per i nomi tecnici (file, directory, variabili di ambiente, ecc.), mentre ‘nidx’ per tutti gli altri tipi di riferimento. Le voci inserite in questi riferimenti, che poi formeranno l’indice generale, vanno scelte in modo da essere uniformi, secondo alcune regole molto semplici. • Si utilizzano le lettere minuscole, a meno che si tratti di nomi particolari che vanno sempre scritti in un modo prestabilito: – i nomi proprietari vanno scritti come indicato dalla casa produttrice; – i nomi di applicativi software vanno scritti come indicato dall’autore; – i nomi di file e directory vanno scritti esattamente come sono, tenendo conto che i file eseguibili vanno indicati senza percorso, mentre gli altri dovrebbero contenerlo; – i nomi di variabili di ambiente vanno scritti esattamente come sono, prefissati dal simbolo dollaro. • Si utilizza solo il singolare; I riferimenti per la generazione dell’indice analitico vanno posti preferibilmente nei luoghi opportuni, in modo da evitare inutili rimandi a pagine che non contengono ciò che si cerca. Per esempio, la parola file potrebbe trovarsi in quasi tutte le pagine di un testo di informatica, mentre è conveniente che l’indice analitico riporti solo le pagine in cui si parla del concetto che questa parola rappresenta. I nomi di programmi eseguibili e di file di dati standard dovrebbero essere inseriti nell’indice analitico ogni volta che appaiono nel testo. 221.7.5 Riferimenti bibliografici e simili Esiste una forma precisa e molto articolata per la stesura delle bibliografie, che corrisponde allo standard ISO 690. A ogni modo, vale la regola generale per cui un riferimento bibliografico deve contenere tutti i dati necessari a reperire il documento a cui si fa riferimento. In condizioni normali, le informazioni essenziali per identificare una pubblicazione sono quelle seguenti: • l’autore o gli autori; • il titolo completo; • l’editore; Stile letterario 2387 • la data di edizione; • l’URI (se il documento è disponibile attraverso la rete). Generalmente è consigliabile comporre gli elenchi bibliografici indicando le opere a partire dall’autore, mettendo il titolo in testo corsivo o inclinato, separando le varie componenti di ogni riferimento bibliografico attraverso delle virgole, come nell’esempio seguente: Claudio Beccari, LaTeX, Guida a un sistema di editoria elettronica, Hoepli, 1991, ISBN 88-203-1931-4 Se non si dispone di un sistema automatico per la gestione dei riferimenti bibliografici, quando si cita un documento all’interno del testo, è bene seguire alcune regole elementari. • I riferimenti ad altri documenti, all’interno del testo normale, vanno fatti indicando il titolo completo, in corsivo o inclinato, aggiungendo il nome dell’autore o degli autori. • Il titolo è separato con una virgola da un eventuale sottotitolo. • I riferimenti a un testo già citato possono essere fatti utilizzando solo il titolo o solo l’autore, o attraverso altri mezzi, purché si sia certi di non creare ambiguità o disagio al lettore. Segue un esempio molto semplice di come può essere fatto un riferimento del genere all’interno del testo normale: Questa sezione fa riferimento a concetti contenuti in LaTeX, Guida a un sistema di editoria elettronica, di Claudio Beccari. 221.8 Riferimenti • Michele Dalla Silvestra, Scrittura testi per l’ILDP • Robert Kiesling, The LDP Style Mini-HOWTO <http://www.linux.org/docs/ldp/howto/HOWTO-INDEX/howtos.html> • Claudio Beccari, LaTeX, Guida a un sistema di editoria elettronica, Hoepli, 1991, ISBN 88-203-1931-4 • M. Fazio, Dizionario e manuale delle unità di misura, Zanichelli • Scienza, tecnologia e arte della stampa e della comunicazione, Arti poligrafiche europee <http://www.apenet.it/grafica/libri/Grafica/Grafica01/indice02.html> <http://www.apenet.it/grafica/libri/Grafica/Grafica02/indice02.html> <http://www.apenet.it/grafica/libri/Grafica/Grafica03/indice02.html> • Scienza, tecnologia e arte della stampa e della comunicazione: Giuseppe Orsello, Preparazione del manoscritto, Arti Poligrafiche Europee <http://www.apenet.it/grafica/libri/Grafica/Grafica01/1206.html> • Marco Gaiarin, Linux Italian HOWTO <http://www.linux.org/docs/ldp/howto/HOWTO-INDEX/howtos.html> Stile letterario 2388 • Maurizio Pistone, Lingua italiana e altra linguistica <http://www.freeweb.org/letteratura/pistone/linguaitaliana.html> • Dictionnaire panlatin de l’informatique <http://www.tele3.net/dicoinfo/_bdt.htm> • NetGlos - The Multilingual Glossary of Internet Terminology <http://wwli.com/translation/netglos/netglos.html> • Amiga Translators’ Organization <http://bilbo.di.unipi.it/~ato-it/> • Bureau International des Poids et Mesures <http://www.bipm.org/> • Bureau International des Poids et Mesures, Le Système international d’unités (SI) <http://www.bipm.org/pdf/brochure-si.pdf> • Bureau International des Poids et Mesures, The International System of Units (SI) (traduzione in inglese) <http://www.bipm.org/pdf/si-brochure.pdf> • National Institute of Standards and Technology, International System of Units (SI) <http://physics.nist.gov/Pubs/SP330/sp330sl.pdf> • National Institute of Standards and Technology, Guide for the Use of the International System of Units (SI), 1995 <http://physics.nist.gov/cuu/pdf/sp811.pdf> • Markus Kuhn, Standardized Units for Use in Information Technology, 1995 <http://www.cl.cam.ac.uk/~mgk25/information-units.txt> • National Institute of Standards and Technology, Prefixes for binary multiples <http://physics.nist.gov/cuu/Units/binary.html> • Excerpts from ISO 690-2, Information and documentation -- Bibliographic references -Part 2: Electronic documents or parts thereof <http://www.nlc-bnc.ca/iso/tc46sc9/standard/690-2e.htm> Appunti di informatica libera 2003.01.01 --- Copyright © 2000-2003 Daniele Giacomini -- daniele @ swlibero.org Capitolo 222 Evoluzione dell’editoria elettronica Con il termine «editoria elettronica», si vuole fare riferimento agli strumenti utilizzabili per produrre documentazione di buona qualità dal punto di vista tipografico. L’approccio di un programma per l’editoria può essere fondamentalmente di due tipi: • a formattazione visuale o WYSIWYG (What you see is what you get);1 • a composizione differita. Nel primo caso, durante la stesura, il documento appare sullo schermo con lo stesso aspetto che avrebbe se venisse stampato in quel momento. Nel secondo, si scrive un file di testo normale con l’inserimento di comandi, come se si trattasse di un linguaggio di programmazione; quindi si passa alla composizione (una sorta di compilazione) attraverso la quale viene generato normalmente il file finale pronto per essere inviato alla stampa. Il primo tipo di composizione è decisamente più pesante sotto l’aspetto elaborativo, prestandosi in particolare per i documenti brevi. Il secondo ha lo svantaggio di non permettere la verifica del risultato finale fino a quando non avviene la composizione, però richiede solo l’utilizzo di un programma normalissimo per la creazione e la modifica di file di testo, mentre solo al momento della composizione c’è bisogno di un’elaborazione consistente. In questo senso è più adatto alla redazione di documenti di grandi dimensioni. Raramente si riescono a trovare programmi in grado di conciliare entrambe le esigenze. Nel sistema operativo Dos, il programma Ventura Publisher è stato un precursore di questa doppia filosofia: permetteva sia la formattazione visuale che differita, perché si basava su un sorgente che poteva essere modificato con un programma di scrittura a caratteri. 222.1 Evoluzione L’editoria elettronica non è più solo cartacea. In particolare esistono gli ipertesti, cioè documenti elettronici la cui consultazione avviene attraverso riferimenti e non in modo puramente sequenziale. In questo senso, se l’editoria elettronica viene vista come mezzo di documentazione generale non più orientata a un supporto particolare, non può avere immediatamente una rappresentazione finale definitiva. Per esempio, un documento in HTML non potrà mai essere identico a un documento stampato. Quando si vuole produrre un documento compatibile con diversi tipi di supporti (carta, ipertesto HTML, guida interna, ecc.) non si possono avere pretese stilistiche particolari; quindi, un programma visuale diventa quasi inutile. A fianco di questi problemi di compatibilità, si aggiungono delle esigenze nuove, come per esempio la possibilità di estrarre dal documento elettronico determinati tipi di informazioni necessarie ad alimentare una base di dati. In questo senso, le informazioni cercate, oltre che riconoscibili all’interno del formato utilizzato, devono essere coerenti e complete. Comunque, anche nell’ambito dell’editoria cartacea tradizionale, la prima esigenza che è stata sentita è quella dell’uniformità stilistica, cosa che sarebbe bene fosse controllabile anche attraverso il sistema elettronico di composizione. 1 «Ciò che si vede è ciò che si ottiene» 2389 2390 Evoluzione dell’editoria elettronica 222.2 Codifica del testo (markup) Il termine markup (o marcatura) deriva dall’ambiente tipografico dove è stato usato per definire le annotazioni fatte su una bozza, allo scopo di segnalare al compositore o al dattilografo il modo con cui alcune parti del testo andavano evidenziate o corrette. A tale proposito, esiste uno standard nella simbologia da utilizzare in questi casi, che si può trovare ancora nei libri di tipografia. Queste annotazioni simboliche possono riferirsi all’aspetto dei caratteri, all’allineamento dei paragrafi, alle spaziature e via dicendo. Nell’editoria elettronica, il concetto alla base del termine markup si è esteso in modo da includere i simboli speciali, o meglio, la codifica inserita nel testo per permetterne l’elaborazione. Volendo generalizzare, la codifica del testo è tutto ciò che ne esplicita l’interpretazione. A livello umano, la stessa punteggiatura e certe forme di spaziatura, sono la codifica che serve a chiarire il significato del testo, diventando parte essenziale di questo. Oggi non sarebbe comprensibile separare concettualmente la punteggiatura dal testo, però in passato è stato così. Basta pensare ai telegrammi, o all’apparizione di questi simboli nella storia della scrittura. 222.2.1 Linguaggio di markup La tecnica di composizione del testo utilizzando l’inserimento di marcatori o di codici, richiede la definizione di una serie di convenzioni, tali da definire un linguaggio di markup . Un tale linguaggio deve specificare quale tipo di marcatura è utilizzabile, quale è richiesta, in che modo si distingua dal testo e quale sia il suo significato. I linguaggi di markup possono essere diversi e si distinguono due gruppi fondamentali: linguaggi procedurali e linguaggi descrittivi. Un linguaggio di markup procedurale serve a definire il processo da svolgere in un punto particolare del documento. È come un linguaggio di programmazione in cui si usano chiamate di funzioni, o di procedure, per compiere le operazioni richieste. Per esempio può trattarsi di ordini riferiti alla scrittura del testo, allo spostamento, alla definizione di margini, del salto pagina e di tutto ciò che si rende necessario. In questo senso, un linguaggio di markup procedurale consente generalmente la definizione completa di tutto ciò che serve a stabilire l’aspetto finale del documento stampato (o visualizzato). Un linguaggio di markup descrittivo, al contrario, usa la codifica dei marcatori per classificare le parti del documento, dando loro un nome. In pratica, si delimitano queste porzioni di testo e si definisce la loro appartenenza a una categoria determinata, identificata da un nome. In tal modo, questo tipo di linguaggio di markup non è in grado di fornire indicazioni sull’aspetto finale del documento, in quanto il suo scopo è solo quello di definire la struttura del testo. Evidentemente sarà compito di un’altra applicazione utilizzare le informazioni sulla struttura del testo per generare un formato finale, secondo regole e definizioni stabilite al di fuori del linguaggio descrittivo stesso. 222.2.2 Vantaggi di un linguaggio descrittivo Un linguaggio di markup descrittivo, nel momento in cui non si prende carico di definire l’aspetto finale del documento, pone l’accento sul contenuto e non sull’apparenza. Questo è fondamentale quando il «documento» viene inteso come informazione pura che possa materializzarsi in forme molto diverse. L’informazione «pura», in quanto tale, richiede anche che sia espressa attraverso un formato indipendente dalle piattaforme, ma soprattutto che sia indipendente dai formati proprietari. Evoluzione dell’editoria elettronica 2391 222.3 SGML L’SGML è un linguaggio di markup descrittivo, definito dallo standard ISO 8879: Information processing---Text and office systems---Standard Generalized Markup Language (SGML), (1986). L’SGML è uno standard internazionale per la definizione di metodi di rappresentazione del testo in forma elettronica in modo indipendente dall’hardware e dal sistema utilizzato. 222.3.1 Linguaggio descrittivo Come accennato, l’SGML è un linguaggio di markup descrittivo. Questo permette a un documento steso secondo questo linguaggio, di essere elaborato da programmi differenti, per scopi diversi, dove la stampa o comunque la semplice lettura testuale del contenuto sia solo uno dei tanti possibili obiettivi da raggiungere. Si è già accennato alla possibilità di estrarre informazioni da un documento per l’utilizzo in una base di dati e questo particolare dovrebbe essere sufficiente per intuire il senso di tale approccio descrittivo. 222.3.2 Definizione del tipo di documento L’SGML utilizza il concetto di «tipo di documento» e di «definizione del tipo di documento». Per la precisione di parla di DTD, ovvero, Document type definition. In pratica, nell’ambito dell’SGML, è necessario che sia stato definito il modo in cui i vari elementi del testo possono essere utilizzati. Ciò che non è definito, non può essere usato, ma quello che è stato definito deve rispettare le regole stabilite. A titolo di esempio, si può immaginare la definizione di un tipo di documento riferito alla scrittura di lettere commerciali. La lettera deve contenere degli elementi essenziali: il mittente, uno o più destinatari, la data, l’oggetto, il corpo, l’indicazione di colui che la firma e la sigla del dattilografo che la scrive materialmente. Tutti questi elementi devono essere presenti, probabilmente anche con un certo ordine (l’indicazione di chi firma deve trovarsi in fondo e non all’inizio). Inoltre, questi elementi possono scomporsi in altri elementi più dettagliati; per esempio, l’informazione sulla persona che firma può comporsi della qualifica, il titolo personale, il nome e il cognome. Il DTD deve prendersi carico di definire tutto questo, stabilendo ciò che è valido e cosa invece non lo è. In questo modo, poi, un documento SGML può essere analizzato da un programma speciale, l’analizzatore SGML (SGML parser), per la verifica del rispetto di queste regole, prima di utilizzare in qualunque modo questo documento. L’SGML, assieme al DTD, garantendo l’uniformità dei documenti dello stesso tipo, consente di uniformare i procedimenti successivi. Per tornare all’esempio precedente, da un punto di vista di puro contenuto del testo, non dovrebbe essere importante l’ordine degli elementi che lo compongono, quando sia possibile distinguerli. Tuttavia, una lettera che inizia con la firma e finisce con l’indicazione del destinatario, non è scritta nel modo corretto; così il DTD potrebbe essere progettato in modo da imporre un certo ordine, a vantaggio delle elaborazioni successive. 222.3.3 Indipendenza dei dati Nella definizione di SGML si è affermato che si tratta di uno standard indipendente dall’hardware e dal sistema utilizzato. Questa indipendenza riguarda la rappresentazione del testo, che non può fare affidamento su una codifica particolare. Si pensi all’uso di lettere accentate e di simboli speciali che non possono essere rappresentati con lo standard tradizionale dell’ASCII a 7 bit. Si pensi a cosa accadrebbe se un testo scritto 2392 Evoluzione dell’editoria elettronica con caratteri ISO Latin 1 venisse elaborato in un sistema configurato per una codifica differente: quei simboli e quelle lettere potrebbero risultare modificati. D’altro canto, la stessa scrittura di determinati caratteri potrebbe essere un problema, non disponendo di una tastiera adatta. Ecco quindi il significato dell’indipendenza dall’hardware (fondamentalmente la tastiera) e dal sistema (principalmente la codifica dei simboli utilizzati). Per ottenere questo risultato, l’SGML utilizza un meccanismo di sostituzione di stringhe, attraverso quelle che vengono chiamate entità, per mezzo del quale si stabilisce il rimpiazzo di tali entità con qualcosa di adeguato, quando il documento viene elaborato. Appunti di informatica libera 2003.01.01 --- Copyright © 2000-2003 Daniele Giacomini -- daniele @ swlibero.org Parte xlii Codifica 223 Introduzione alla codifica universale dei caratteri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2394 223.1 Lettera, codifica e carattere da stampa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2394 223.2 Ambiguità nel concetto di «carattere» . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2396 223.3 Unicode e ISO 10646 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2399 223.4 Apparenza e realtà . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2403 223.5 Riferimenti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2403 224 Esempi di codifica dei caratteri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2405 224.1 ASCII (ISO 646) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2405 224.2 ISO 8859-n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2407 224.3 Riferimenti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2410 2393 Capitolo 223 Introduzione alla codifica universale dei caratteri La codifica dei caratteri, intendendo ciò come il modo di rappresentare i simboli tipografici in forma elettronica, diventa un problema serio nel momento in cui si esce dallo schema abituale delle lingue di origine latina. Nella storia dell’informatica è stata definita una quantità enorme di codifiche differenti, per adattare la limitatezza degli 8 bit tradizionali all’insieme di caratteri che serve in ogni circostanza particolare. Inoltre, nelle situazioni in cui 8 bit non potevano bastare, sono state ideate codifiche più complesse, attraverso l’abbinamento di sequenze di simboli elementari che ne rappresentano uno più complesso. In generale, verrebbe da pensare che sarebbe stato meglio prevedere subito il problema, definendo delle unità di codifica più grandi (non più il byte, ma stringhe binarie più lunghe). Tuttavia, c’è da considerare che proprio la semplicità dell’alfabeto inglese (che non ha nemmeno le lettere accentate) ha permesso lo sviluppo rapido di tecnologia relativamente «semplice», che altrimenti sarebbe stata materialmente irraggiungibile. Il byte stesso è stata una grande conquista. Ancora oggi ci sono sistemi di comunicazione che riconoscono unità di codifica a soli 7 bit, dove in pratica si può usare solo l’ASCII; prima ancora sono state utilizzate anche unità di codifica a soli 6 bit. Questo capitolo ha l’intento di raccogliere alcuni concetti legati alla codifica dei caratteri, assieme a qualche indicazione sul funzionamento dello standard di codifica universale: Unicode o ISO 10646. Alcuni concetti che sono trattati qui, riprendono quanto già descritto in parte nel capitolo 220. 223.1 Lettera, codifica e carattere da stampa Per comprendere il problema della codifica, è necessario considerare prima i problemi che riguardano la definizione dei caratteri da stampa. La prima fase è la definizione di un repertorio astratto, all’interno del quale si elencano, senza un ordine preciso, le lettere e gli altri segni necessari per un certo scopo. L’insieme di questi simboli è astratto, nel senso che non è ancora stabilito l’aspetto finale, compito riservato a una fase successiva. Il simbolo di un repertorio astratto è qualcosa di diverso dal simbolo che compone un carattere da stampa, dal momento che il secondo rappresenta il modo preciso in cui il simbolo astratto viene reso tipograficamente. Per comprendere il concetto, si pensi alla lettera «a» e all’aspetto che questo simbolo astratto può avere utilizzando stili, serie e corpi differenti. Evidentemente, si tratta sempre della stessa lettera, ma resa in modo diverso. Figura 223.1. La lettera «a» minuscola resa tipograficamente in modo differente. Alcuni gruppi di simboli astratti tendono a essere rappresentati tipograficamente in un simbolo solo, in un legato, ovvero attraverso l’avvicinamento e la sovrapposizione parziale. Il caso tipico è rappresentato dalla sequenza di lettere «fi» e «ffi», come si vede nella figura 223.2. In certi casi, la sequenza di lettere che si avvicina rappresenta una parola intera, generando così un «logotipo»; spesso, la loro importanza storica ha fatto sì che questi siano diventati dei simboli astratti 2394 Introduzione alla codifica universale dei caratteri 2395 autonomi. Per esempio, la parola latina «et» è diventata la e-commerciale odierna, «&»; la parola latina «ad» è diventata la chiocciola odierna, «@».1 Figura 223.2. Il legato «fi» e «ffi». La composizione tipografica elettronica, può avvenire attraverso la sovrapposizione di simboli elementari differenti, senza la necessità di legarli assieme. Nelle lingue di origine latina, il caso più comune di questa possibilità si ha con gli accenti, che potrebbero essere simboli tipografici separati da sovrapporre alle lettere a cui sono destinati. Nello stesso modo, il repertorio di simboli astratti potrebbe essere realizzato con questo criterio; per esempio, per fare riferimento a un simbolo complesso potrebbe essere necessario indicare una sequenza di simboli astratti elementari. Alcune lingue hanno dei simboli che nella composizione tipografica devono cambiare forma a seconda del contesto. Per comprendere il concetto, si può pensare a una scrittura manuale, in cui le lettere cambiano leggermente forma a seconda di ciò che appare prima e dopo; chi conosce una scrittura stenografica manuale, può intendere ancora meglio il problema. Ad aggravare ancora di più il problema, l’adattamento contestuale di un simbolo potrebbe dipendere da una scelta stilistica, in parte arbitraria. A volte, la larghezza di un testo deve essere adattata per esigenze estetiche, come avviene nel caso dell’allineamento simultaneo a sinistra e a destra. Nelle lingue di origine latina si ottiene questo attraverso l’allargamento degli spazi tra le parole e tra le lettere all’interno delle parole; tuttavia, alcune lingue richiedono degli adattamenti differenti, per esempio attraverso l’introduzione di altri simboli appropriati. Da quello che è stato scritto si intende che la composizione tipografica elettronica si può considerare come l’ultima fase di un processo composto da tre livelli: definizione di un repertorio astratto di simboli; definizione di una codifica; composizione tipografica a partire dalla codifica. repertorio astratto ----> codifica ----> composizione La codifica non può corrispondere esattamente al repertorio astratto ideale: deve fare delle scelte. In generale, il repertorio simbolico preso in considerazione dalla codifica è identificabile come un insieme di punti di codifica (code point, secondo la documentazione di Unicode). I problemi legati alla composizione tipografica che sono stati descritti, sono solo alcuni di quelli che si incontrano. A seconda dei casi, implicano un approccio differente per ciò che riguarda la codifica e la composizione. In breve: 1. lo stile tipografico è qualcosa che normalmente è gestito dal sistema di composizione, senza richiedere la definizione di punti di codifica differenti; 2. il legato può essere un problema risolto a livello di composizione finale, oppure può richiedere la definizione di punti di codifica aggiuntivi, quando si tratta di legati molto importanti o di logotipi; 3. l’adattamento contestuale richiede spesso la definizione di tanti punti di codifica quante 1 Nella nostra lingua si è perso l’uso di questo legato, che oggi si riacquisisce solo attraverso la lingua inglese, pertanto lo si conosce solitamente solo nella sua definizione inglese: at Introduzione alla codifica universale dei caratteri 2396 sono le varianti contestuali del simbolo astratto, specialmente se esiste un margine di scelta da parte dell’autore; 4. l’adattamento della larghezza del testo dovrebbe essere compito del sistema di composizione, anche quando questo implica l’inserzione di simboli speciali. 223.2 Ambiguità nel concetto di «carattere» In informatica, il termine «carattere» ha acquisito un significato ambiguo che dipende dal contesto. Per esempio, può riferirsi a un simbolo del repertorio astratto, a un punto di codifica, all’unità di memorizzazione (unità di codifica, o code unit), o al segno che viene ottenuto alla fine del processo di composizione.2 Di certo non si può pretendere che si smetta di usare questa parola per passare invece a una terminologia più precisa. Tuttavia è importante rendersi conto della vastità della cosa e dei problemi che ci stanno sotto. Il modello di Unicode suddivide il problema della codifica in cinque livelli: 1. ACR (Abstract character repertoire) definizione di un repertorio astratto di simboli; 2. CCS (Coded character set) definizione di una mappa in cui si abbina un numero intero, non negativo, a ogni simbolo del repertorio astratto che si intende gestire; 3. CEF (Character encoding form) definizione di una mappa in cui si abbinano i numeri ottenuti dal livello precedente a un insieme di sequenze dell’unità di codifica prescelta; 4. CES (Character encoding scheme) definizione di una mappa di trasformazione delle unità di codifica in una sequenza seriale di byte; 5. TES (Transfer encoding syntax) definizione di un metodo reversibile di trasformazione dei dati codificati in base alle limitazioni del mezzo trasmissivo. Da un punto di vista leggermente differente, si potrebbe scomporre il problema in strati, per distinguere le fasi che vanno dalla scrittura alla trasmissione del testo e dalla ricezione del testo alla lettura. La scrittura potrebbe essere descritta con l’elenco di operazioni seguenti: 1. selezioni dei simboli e digitazione attraverso la tastiera (o un altro mezzo); 2. codifica, attraverso cui si trasforma il simbolo in un numero intero non negativo; 3. trasformazione in unità di codifica, in base alla forma prescelta; 4. adattamento in sequenze di byte; 5. adattamento prima del trasferimento dei dati. 2 Per fare un esempio in merito all’unità di codifica, basta pensare al byte, che spesso viene confuso con il carattere, mentre ormai è da intendersi come un’unità di memorizzazione troppo piccola per questo scopo nel sistema globale. Introduzione alla codifica universale dei caratteri 2397 Il processo di lettura dei dati, a partire dalla ricezione, è opposto: 1. interpretazione dei dati ricevuti e ricostruzione delle sequenze di byte di partenza; 2. trasformazione delle sequenze di byte in sequenze di unità di codifica; 3. trasformazione dalle sequenze di unità di codifica in numeri interi non negativi; 4. decodifica dei numeri interi non negativi; 5. composizione tipografica (su schermo o su carta). Prima di questa sezione è già stato affrontato il problema dell’abbinamento tra il repertorio astratto di simboli e la codifica, senza precisare in che modo sia organizzata questa ultima. Nelle sezioni seguenti si accenna alle problematiche successive. 223.2.1 CCS: insieme di caratteri codificato L’insieme di caratteri codificato è in pratica il repertorio simbolico disponibile effettivamente, ottenuto dopo la definizione di un repertorio astratto e dopo lo studio dei problemi legati alla cultura e alle consuetudini del linguaggio per il quale è stato realizzato. Questo insieme di caratteri abbina un numero intero a ogni simbolo, senza bisogno che ci sia continuità nella sequenza di tale valore (l’unica limitazione è quella per cui deve trattarsi di un valore non negativo). Il numero che rappresenta il simbolo di un insieme di caratteri codificato, è il punto di codifica. Nella documentazione tecnica si fa spesso riferimento al concetto di «insieme di caratteri», ovvero character set, per intendere quello che qui si indica come «insieme di caratteri codificato», ovvero CCS, Coded character set. Alcuni esempi tradizionali di insiemi di caratteri codificati sono: • ASCII (ISO 646) 127 punti di codifica; • ISO 8859-1 i primi 127 punti di codifica sono uguali all’ASCII; • ISO 8859-2 i primi 127 punti di codifica sono uguali all’ASCII, mentre nella parte restante il repertorio dei simboli è diverso dall’ISO 8859-1. Alcuni insiemi di caratteri codificati prevedono l’abbinamento con una descrizione (in inglese), allo scopo di facilitarne l’identificazione. Si utilizza questa descrizione per evitare ambiguità nell’identificazione del simbolo, quando questo potrebbe essere confuso con un altro, o più semplicemente quando potrebbe essere male interpretato. Per rappresentare un punto di codifica, basta indicare il suo numero intero (qualunque sia la sua base di numerazione). Di solito, per evitare ambiguità, quando si tratta di Unicode o di ISO 10646, si fa uso normalmente della forma ‘U+n n n n ’, oppure ‘U-nn n n n n n n ’, dove n è una 2398 Introduzione alla codifica universale dei caratteri cifra esadecimale. Evidentemente, la seconda forma è utile per individuare punti di codifica più grandi.3 Tuttavia, in questo documento si preferisce l’uso di una forma differente, mediata dall’XML, ‘#xn ’, dove n rappresenta una o più cifre esadecimali in base alla necessità. In questa fase della scomposizione del problema della codifica, il «carattere» è il numero intero che rappresenta il punto di codifica. Attraverso un linguaggio di programmazione che sia adeguato al problema della codifica universale, il tipo di dati carattere deve corrispondere a un intero senza segno per il quale non ci si pone il problema del limite (anche se in questo momento dovrebbe essere almeno un intero a 32 bit); di conseguenza, il tipo stringa dovrebbe essere un array del tipo carattere. 223.2.2 CEF: forma codificata del carattere La forma codificata del carattere è il risultato di una trasformazione dal numero intero non negativo che costituisce il livello precedente, in una sequenza di unità di codifica. L’unità di codifica è un raggruppamento di bit di una lunghezza opportuna. La sequenza di unità di codifica non è composta necessariamente dalla stessa quantità di queste unità per tutti gli elementi dell’insieme di caratteri. A questo proposito, si distingue tra forme codificate del carattere a lunghezza fissa e a lunghezza variabile. L’esempio più semplice di forma codificata del carattere a lunghezza fissa è dato dall’ASCII tradizionale: l’insieme di caratteri codificato è costituito da 128 punti di codifica, rappresentati da tutti gli interi che vanno da 0 a 127. L’unità di codifica utilizzata in questa situazione è un gruppo singolo di 7 bit con i quali si rappresenta lo stesso numero intero. Il caso più comune di forma codificata del carattere a lunghezza variabile è dato dall’UTF-8, che utilizza un’unità di codifica di un ottetto (un byte), in cui i punti di codifica con valori tra 0 e 127 (da 0016 a 7F16) utilizzano una sola unità di codifica, mentre tutti gli altri ne utilizzano più di una. In fase di interpretazione delle sequenze di unità di codifica si possono presentare i casi seguenti: 1. la sequenza potrebbe non essere valida, perché incompleta, o perché esclusa esplicitamente; 2. la sequenza potrebbe fare riferimento a un punto di codifica possibile ma non ancora assegnato a un simbolo; 3. la sequenza potrebbe corrispondere a un punto di codifica assegnato a un simbolo stabilito, oppure lasciato all’attribuzione libera senza un vincolo preciso. Il problema delle sequenze incomplete si intende nel momento in cui si accetta il fatto che un forma di codifica possa prevedere una lunghezza variabile delle sequenze di unità di codifica. Il caso dei punti di codifica lasciati al libero arbitrio degli utilizzatori, è una particolarità della codifica universale (Unicode e ISO 10646); se ne può comprendere la necessità di fronte a un sistema di codifica che vuole essere completo, ma che in pratica è appena all’inizio della sua opera di catalogazione. A questo livello della scomposizione del problema, il «carattere» è ciò che idealmente è scritto in un «file di testo» (non più solo un «file ASCII»). Anche se è stato stabilito in che modo è organizzato l’insieme di caratteri codificato, la sua rappresentazione binaria «ideale» nel file di testo 3 Per la precisione, questa notazione è la rappresentazione delle codifiche UCS-2 e UCS-4 a cui non si intende fare riferimento direttamente. In generale, non c’è alcun bisogno di rappresentare un punto di codifica in questo modo; tuttavia, si tratta di una simbologia immediata che dovrebbe semplificare la lettura e la comprensione del testo. Introduzione alla codifica universale dei caratteri 2399 dipende dalla forma prescelta. Qui si parla di rappresentazione ideale, perché la rappresentazione reale dipende dal livello successivo, in cui tutto viene tradotto a livello di byte. 223.2.3 CES: schema di codifica del carattere Lo schema di codifica del carattere è un sistema di trasformazione attraverso il quale, le unità di codifica vengono rese in sequenze di byte messe in serie. Per tornare all’esempio dell’ASCII, l’unità di codifica è di 7 bit, ma il «carattere» ASCII si gestisce in pratica all’interno di un byte, dove il bit più significativo viene lasciato azzerato. In generale, il byte è un’unità di memorizzazione standard in tutte le architetture dei sistemi elaborativi e in tutti i sistemi di trasmissione dati. Questo spiega la necessità di trasferire tutto a livello di byte o di multipli di questa unità. Dovendo utilizzare più byte per rappresentare un oggetto unico, si pone il problema dello scambio tra coppie di byte che avviene in alcune architetture. Come è noto, si distingue tra big-endian, in cui il primo byte è quello più significativo, e little-endian, in cui il primo byte è quello meno significativo. Pertanto, in questa situazione, si impone la necessità di specificare l’ordine dei byte. 223.2.4 TES: sintassi di codifica per il trasferimento La sintassi di codifica per il trasferimento è un metodo di trasformazione reversibile di una codifica, che si deve attuare a causa di qualche tipo di esigenza. Per esempio: • la necessità di evitare l’utilizzo di alcuni valori nei byte che potrebbero confondere un sistema di comunicazione o di memorizzazione; • la necessità di ridurre la dimensione dei dati utilizzando algoritmi di compressione. Mentre il secondo caso dovrebbe essere chiaro, per comprendere il primo basta pensare alle limitazioni che ha storicamente il protocollo SMTP (posta elettronica), per cui è necessario evitare di trasmettere byte in cui il primo bit sia diverso da zero. 223.3 Unicode e ISO 10646 Il lavoro per la realizzazione del sistema di codifica universale non può partire da zero, per l’esigenza di mantenere qualche forma di compatibilità con il passato (diversamente, non verrebbe nemmeno preso in considerazione). Pertanto, le incongruenze che si possono rilevare sono dovute principalmente a questo motivo: la necessità di riutilizzare gli insiemi di caratteri codificati più importanti che erano già esistenti. Unicode e ISO 10646 sono due standard compatibili reciprocamente che definiscono un insieme di caratteri codificato particolarmente grande, che poi deve essere trasformato nella forma codificata del carattere prescelta per la sua rappresentazione pratica in unità di codifica. Pertanto, quando di parla di Unicode, o di ISO 10646, senza specificare altro, si pensa generalmente ai punti di codifica e non alla rappresentazione finale.4 I primi punti di codifica di questi standard corrispondono esattamente all’ISO 8859-1. Per esempio: #x20 è lo spazio normale; #xA0 è lo spazio non interrompibile; #xAB sono le virgolette angolari aperte; #xBB sono le virgolette angolari chiuse. 4 In generale, per maggiore chiarezza, i punti di codifica dell’Unicode e di ISO 10646 si indicano nella forma ‘U+n nn n ’, oppure ‘U-nn n n n n nn ’, dove n è una cifra esadecimale; ma come è già stato mostrato, qui si userà la notazione ‘#xn ’ dell’XML. Introduzione alla codifica universale dei caratteri 2400 Attualmente, la codifica universale utilizza principalmente tre forme codificate del carattere UTF (Unicode transformation format): UTF-8, UTF-16 e UTF-32. Ogni forma codificata del carattere del tipo UTF-n rappresenta un punto di codifica come una sequenza di una o più unità di codifica (che a sua volta occupa n bit), ottenuta attraverso una trasformazione reversibile del valore. Con questo sistema, i punti di codifica che possono essere rappresentati vanno teoricamente da #x0 a #x7FFFFFFF (in particolare, secondo Unicode si arriva solo fino a #x10FFFF), salvo alcuni valori che sono stati esclusi espressamente. I punti di codifica esclusi più importanti sono #xFFFE e #xFFFF. Le forme codificate del carattere che utilizzano le unità di codifica più piccole, richiedono l’uso di sequenze multiple di tali unità con maggiore frequenza. Per esempio, si può osservare il caso di UTF-8, in cui l’unità di codifica è il byte (un ottetto): mano a mano che il valore del punto di codifica cresce, è necessario utilizzare più unità di codifica per la sua rappresentazione. È necessario sottolineare il fatto che i valori che compongono l’insieme dei punti di codifica, non vengono trasferiti tali e quali nella forma codificata, dal momento che ci possono essere delle limitazioni nella rappresentazione. Allo stato attuale dello sviluppo della codifica universale, le varie forme codificate del carattere possono utilizzare gli spazi seguenti: • UTF-8 da uno a sei unità di codifica da 8 bit (mentre secondo Unicode, che è più restrittivo dello standard ISO 10646, si hanno al massimo quattro unità); • UTF-16 da uno a due unità di codifica da 16 bit; • UTF-32 attualmente si prevede una sola unità di codifica da 32 bit. 223.3.1 UTF-8 UTF sta per Unicode transformation format e significa implicitamente che si tratta di una mappa di trasformazione da punti di codifica Unicode a unità di codifica (è già stato descritto il fatto che il numero che segue la sigla UTF-n indica la dimensione in bit dell’unità di codifica). In particolare, vale la pena di osservare un po’ meglio UTF-8, che è il cardine della transizione verso la codifica universale nei sistemi operativi in cui non è conveniente l’utilizzo di unità di codifica più grandi. In effetti, UTF-8 è un sistema molto complesso per rappresentare simboli di qualunque lingua diversa dall’inglese, perché richiede spesso l’utilizzo di più unità per un solo simbolo. Le caratteristiche di UTF-8 sono le seguenti: • i punti di codifica da #x0 a #x7F, corrispondenti in pratica all’ASCII, sono tradotti semplicemente in byte da 0016 a 7F16, esattamente come si fa già con l’ASCII stesso; • i punti di codifica che vanno da #x80 in su, vengono tradotti in sequenze multiple di byte, ognuno dei quali ha il bit più significativo a uno, così da evitare che i byte da 0016 a 7F16 possano apparire all’interno delle sequenze multiple; Introduzione alla codifica universale dei caratteri 2401 • il primo byte di una sequenza multipla che rappresenta un punto di codifica che vada da #x80 in su, contiene sempre valori nell’intervallo da C016 a FD16 e serve a indicare quanti byte vengono utilizzati per rappresentare il carattere; • i byte di una sequenza multipla che sono successivi al primo contengono valori che vanno da 8016 a BF16; • si possono definire sequenze di byte in numero massimo di sei; • i valori FE16 e FF16 non sono mai usati. La tabella 223.1 dovrebbe chiarire meglio il concetto, abbinando i valori dei punti di codifica Unicode alle sequenze di byte con cui possono essere rappresentati. Si osservi che la lettera x serve a indicare un bit variabile. Tabella 223.1. Sequenze multi-byte teoriche nell’UTF-8. da #x0 #x80 #x800 #x10000 #x200000 #x4000000 a #x7F #x7FF #xFFFF #x1FFFFF #x3FFFFFF #x7FFFFFFF sequenze di ottetti 0xxxxxx x 110xx xxx 10xxxx x x 1110xx xx 10xxx x xx 10x xx xx x 11110xxx 10xx x xx x 10xx xx x x 10xx x xx x 111110x x 10x x xx x x 10xxx xx x 10x xx x xx 10xx xx xx 1111110x 10x xxx x x 10xx xx x x 10xx x xx x 10xxx xx x 10x xx x xx Un esempio dovrebbe chiarire ancora meglio il meccanismo. La lettera accentata «è» si rappresenta attraverso il punto di codifica #xE8, che in pratica si può rendere in binario come 1110 10002, si traduce in UTF-8 come si vede nella figura 223.3. Figura 223.3. #xE8 in UTF-8. 1110 1000 | | si scinde a gruppi di sei bit V 11 101000 | | si inseriscono i bit iniziali secondo lo schema di UTF-8 V 110000 11 10 101000 primo secondo ottetto ottetto 1100 0011 1010 1000 0xc3 0xa8 Un altro esempio interessante è il punto di codifica #xFEFF (1111 1110 1111 11112); lo si vede nella figura 223.4. Figura 223.4. #xFEFF in UTF-8. 1111 1110 1111 1111 | | si scinde a gruppi di sei bit V 1111 111011 111111 | | si inseriscono i bit iniziali secondo lo schema di UTF-8 V 1110 1111 10 111011 10 111111 primo secondo terzo ottetto ottetto ottetto 1110 1111 1011 1011 1011 1111 0xef 0xbb 0xbf Introduzione alla codifica universale dei caratteri 2402 Da questo si dovrebbe intendere il passaggio a un numero superiore di byte. In base al modello di UTF-8, si potrebbero realizzare anche sequenze più lunghe del necessario per rappresentare un punto di codifica. Evidentemente, è compito del software che le genera evitare di sprecare dello spazio inutilmente. 223.3.2 Schema di codifica e firma di riconoscimento Di fronte a diverse forme codificate del carattere UTF c’è la necessità di poterle identificare facilmente. Per questo si utilizza una sorta di firma iniziale, costituita in pratica dal punto di codifica #xFEFF, che quando viene trasformato in base allo schema di codifica del carattere, permette anche di controllare se l’ordine dei byte è normale o è stato invertito. Il punto di codifica #xFEFF viene anche identificato con il nome ZWNBSP, ovvero Zero width no-break space; tuttavia, anche se si intende che si tratta di qualcosa di «innoquo» (uno spazio non interrompibile di ampiezza nulla), se è stato inserito come firma iniziale, non va inteso come parte del testo. Questo significa, che i programmi per la gestione di file di testo devono tenere conto che la firma iniziale va tolta prima di fare qualunque elaborazione (si pensi al concatenamento con un comando ‘cat’ o simile). Gli schemi di codifica del carattere riferiti alle forme codificate UTF, si possono precisare aggiungendo delle sigle alla fine del nome UTF-n . La tabella 223.2 mostra gli schemi di codifica UTF-n *, assieme alla firma iniziale (quando questa è prevista). Tabella 223.2. Schemi di codifica UTF-n . Schema UTF-8 UTF-8N UTF-16 UTF-16 UTF-16 UTF-16BE UTF-16LE UTF-32 UTF-32 UTF-32 UTF-32BE UTF-32LE Firma iniziale EFBBBF16 FEFF16 FFFE16 0000FEFF16 FFFE000016 Note In condizioni normali è prevista la firma iniziale. Si indica esplicitamente l’assenza della firma. UTF-16 big-endian in modo predefinito. UTF-16 big-endian. UTF-16 little-endian. UTF-16 big-endian senza firma. UTF-16 little-endian senza firma. UTF-32 big-endian in modo predefinito. UTF-32 big-endian. UTF-32 little-endian. UTF-32 big-endian senza firma. UTF-32 little-endian senza firma. 223.3.3 Tipi di dati nuovi Si è già accennato al modo in cui un linguaggio di programmazione può gestire i punti di codifica di questo tipo. Tuttavia, non si può dimenticare il passato; così, in tutte le situazioni in cui il «carattere» è implicitamente un intero senza segno a 8 bit, è necessario usare un’altra definizione per i punti di codifica: il carattere esteso, ovvero wide char. Nello stesso modo, dovendo parlare di stringhe, se c’è bisogno di chiarire che si tratta di una stringa secondo Unicode o ISO 10646, si parla di stringa estesa, ovvero di wide string. Introduzione alla codifica universale dei caratteri 2403 223.4 Apparenza e realtà La disponibilità di un sistema di codifica che faccia riferimento a un repertorio simbolico molto ampio, risolve tanti problemi del passato in cui era necessario risparmiare. Per esempio, nell’ASCII tradizionale, il trattino è unico (non si distingue la sua lunghezza) ed è anche un segno «meno». Disponendo di un repertorio molto grande, diventa importante utilizzare il simbolo giusto in base al contesto. Per esempio, la lettera latina «A» maiuscola, è diversa dalla lettera greca alfa maiuscola, anche se i due simboli possono avere lo stesso aspetto. La descrizione che viene abbinata ai punti di codifica serve proprio per questo, in modo da evitare confusione. Per fare un esempio più convincente, si pensi alla lettera «ß» nell’insieme ISO 8859-1. Il nome abbinato a questa lettera è «LATIN SMALL LETTER SHARP S»; come si legge non si tratta della lettera greca beta, ma di qualcosa di diverso. Per la precisione è un legato che si usa nella lingua tedesca; in mancanza del segno tipografico può essere reso come «ss» (infatti si tratta di una lettera minuscola). Utilizzare questo simbolo al posto della lettera beta sarebbe un errore; infatti, un sistema di composizione o di lettura, potrebbe anche decidere di convertire il segno nella forma semplificata che è appena stata mostrata. 223.5 Riferimenti • Jukka Korpela, A tutorial on character code issue <http://www.hut.fi/~jkorpela/chars.html> • Unicode Home Page <http://www.unicode.org/> • Mark Davis, Draft Unicode FAQ <http://www.unicode.org/unicode/faq/> • Ken Whistler, Mark Davis, Unicode Technical Report #17, Character Encoding Model <http://www.unicode.org/unicode/reports/tr17/> • Mark Davis, Forms of Unicode <http://www.ibm.com/developerworks/library/utfencodingforms/> • C. Weider, C. Preston, K. Simonsen, H. Alvestrand, R. Atkinson, M. Crispin, P. Svanberg, RFC 2130: The Report of the IAB Character Set Workshop held 29 February - 1 March, 1996 <http://www.cis.ohio-state.edu/cgi-bin/rfc/rfc2130.html> <http://www.cis.ohio-state.edu/cs/Services/rfc/rfc-text/rfc2130.txt> • Markus Kuhn, UTF-8 and Unicode FAQ for UNIX/Linux <http://www.cl.cam.ac.uk/~mgk25/unicode.html> • Bruno Haible, The Unicode HOWTO <ftp://ftp.ilog.fr/pub/Users/haible/utf8/Unicode-HOWTO.html> • D. Goldsmith, M. Davis, RFC 2152: UTF-7, a mail-safe transformation format of Unicode, 1997 <http://www.cis.ohio-state.edu/cgi-bin/rfc/rfc2152.html> <http://www.cis.ohio-state.edu/cs/Services/rfc/rfc-text/rfc2152.txt> Introduzione alla codifica universale dei caratteri 2404 • F. Yergeau, RFC 2279: UTF-8, a transformation format of ISO 10646, 1998 <http://www.cis.ohio-state.edu/cgi-bin/rfc/rfc2279.html> <http://www.cis.ohio-state.edu/cs/Services/rfc/rfc-text/rfc2279.txt> • Indrek Hein, An online character database <http://www.eki.ee/letter/> Appunti di informatica libera 2003.01.01 --- Copyright © 2000-2003 Daniele Giacomini -- daniele @ swlibero.org Capitolo 224 Esempi di codifica dei caratteri In questo capitolo si raccolgono le descrizioni di alcuni esempi di insiemi di caratteri codificati e di forme codificate del carattere tradizionali. È il caso di ricordare che nella sezione 342.1.1 viene descritto il funzionamento del programma di servizio ‘recode’, specializzato nella conversione dei file di testo. 224.1 ASCII (ISO 646) L’ASCII è una codifica molto semplice, in cui ogni punto di codifica corrisponde direttamente a un gruppo di 7 bit, inteso come un intero senza segno, senza bisogno di trasformazioni. Sulla base di questa codifica si sono sviluppate molte varianti, soprattutto a 8 bit. Tuttavia, oggi, quando si parla di ASCII si tende a fare riferimento prevalentemente allo standard originale, in cui si utilizzavano valori compresi tra 0 e 127, per rappresentare i quali bastano solo 7 bit. Eventualmente, volendo essere precisi, per fare riferimento all’ASCII tradizionale si può utilizzare la denominazione «US-ASCII». L’ASCII non si occupa solo di definire la codifica dei segni tipografici, ma include anche dei codici di controllo, ai quali abbina un nome, ma senza potervi attribuire un significato univoco valido in tutti i contesti. Si tratta dei punti di codifica da 0 a 31 e del 127 in decimale (il punto di codifica 32 rappresenta lo spazio normale). La tabella 224.1 mostra nel dettaglio la codifica ASCII. Tabella 224.1. US-ASCII (ISO 646). Binario 000000002 000000012 000000102 000000112 000001002 000001012 000001102 000001112 000010002 000010012 000010102 000010112 000011002 000011012 000011102 000011112 000100002 000100012 000100102 000100112 000101002 000101012 000101102 000101112 000110002 000110012 000110102 000110112 000111002 Esadecimale 0016 0116 0216 0316 0416 0516 0616 0716 0816 0916 0A16 0B16 0C16 0D16 0E16 0F16 1016 1116 1216 1316 1416 1516 1616 1716 1816 1916 1A16 1B16 1C16 Ottale 0008 0018 0028 0038 0048 0058 0068 0078 0108 0118 0128 0138 0148 0158 0168 0178 0208 0218 0228 0238 0248 0258 0268 0278 0308 0318 0328 0338 0348 2405 Decimale 00010 00110 00210 00310 00410 00510 00610 00710 00810 00910 01010 01110 01210 01310 01410 01510 01610 01710 01810 01910 02010 02110 02210 02310 02410 02510 02610 02710 02810 Carattere <NUL> <SOH> <STX> <ETX> <EOT> <ENQ> <ACK> <BEL> <BS> <HT> <LF> <VT> <FF> <CR> <SO> <SI> <DLE> <DC1> <DC2> <DC3> <DC4> <NAK> <SYN> <ETB> <CAN> <EM> <SUB> <ESC> <FS> \0 \a \b \t \n \v \f \r Esempi di codifica dei caratteri 2406 Binario 000111012 000111102 000111112 001000002 001000012 001000102 001000112 001001002 001001012 001001102 001001112 001010002 001010012 001010102 001010112 001011002 001011012 001011102 001011112 001100002 001100012 001100102 001100112 001101002 001101012 001101102 001101112 001110002 001110012 001110102 001110112 001111002 001111012 001111102 001111112 010000002 010000012 010000102 010000112 010001002 010001012 010001102 010001112 010010002 010010012 010010102 010010112 010011002 010011012 010011102 010011112 010100002 010100012 010100102 010100112 010101002 010101012 Esadecimale 1D16 1E16 1F16 2016 2116 2216 2316 2416 2516 2616 2716 2816 2916 2A16 2B16 2C16 2D16 2E16 2F16 3016 3116 3216 3316 3416 3516 3616 3716 3816 3916 3A16 3B16 3C16 3D16 3E16 3F16 4016 4116 4216 4316 4416 4516 4616 4716 4816 4916 4A16 4B16 4C16 4D16 4E16 4F16 5016 5116 5216 5316 5416 5516 Ottale 0358 0368 0378 0408 0418 0428 0438 0448 0458 0468 0478 0508 0518 0528 0538 0548 0558 0568 0578 0608 0618 0628 0638 0648 0658 0668 0678 0708 0718 0728 0738 0748 0758 0768 0778 1008 1018 1028 1038 1048 1058 1068 1078 1108 1118 1128 1138 1148 1158 1168 1178 1208 1218 1228 1238 1248 1258 Decimale 02910 03010 03110 03210 03310 03410 03510 03610 03710 03810 03910 04010 04110 04210 04310 04410 04510 04610 04710 04810 04910 05010 05110 05210 05310 05410 05510 05610 05710 05810 05910 06010 06110 06210 06310 06410 06510 06610 06710 06810 06910 07010 07110 07210 07310 07410 07510 07610 07710 07810 07910 08010 08110 08210 08310 08410 08510 Carattere <GS> <RS> <US> <SP> ! " # $ % & ’ ( ) * + , . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P S R S T U Esempi di codifica dei caratteri Binario 010101102 010101112 010110002 010110012 010110102 010110112 010111002 010111012 010111102 010111112 011000002 011000012 011000102 011000112 011001002 011001012 011001102 011001112 011010002 011010012 011010102 011010112 011011002 011011012 011011102 011011112 011100002 011100012 011100102 011100112 011101002 011101012 011101102 011101112 011110002 011110012 011110102 011110112 011111002 011111012 011111102 011111112 Esadecimale 5616 5716 5816 5916 5A16 5B16 5C16 5D16 5E16 5F16 6016 6116 6216 6316 6416 6516 6616 6716 6816 6916 6A16 6B16 6C16 6D16 6E16 6F16 7016 7116 7216 7316 7416 7516 7616 7716 7816 7916 7A16 7B16 7C16 7D16 7E16 7F16 2407 Ottale 1268 1278 1308 1318 1328 1338 1348 1358 1368 1378 1408 1418 1428 1438 1448 1458 1468 1478 1508 1518 1528 1538 1548 1558 1568 1578 1608 1618 1628 1638 1648 1658 1668 1678 1708 1718 1728 1738 1748 1758 1768 1778 Decimale 08610 08710 08810 08910 09010 09110 09210 09310 09410 09510 09610 09710 09810 09910 10010 10110 10210 10310 10410 10510 10610 10710 10810 10910 11010 11110 11210 11310 11410 11510 11610 11710 11810 11910 12010 12110 12210 12310 12410 12510 12610 12710 Carattere V W X Y Z [ \ ] ^ _ ‘ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ \\ <DEL> 224.2 ISO 8859-n Le codifiche ISO 8859-n , dove n è un numero da 1 a 15, rappresentano per il passato l’evoluzione più coerente dell’ASCII, in quanto utilizzano tutte gli stessi punti di codifica iniziali da 0 a 127, corrispondenti esattamente all’ASCII originale. Come nel caso dell’ASCII, non c’è distinzione tra punto di codifica e forma codificata del carattere; in questa situazione si usano valori fino a 255, attraverso un byte intero. Le codifiche ISO 8859-n introducono altri codici di controllo, nell’intervallo di punti di codifica che va da 128 a 159. Esempi di codifica dei caratteri 2408 Per quanto riguarda le lingue occidentali, la codifica ISO 8859 più comune è ISO 8859-1, conosciuta anche come ISO Latin 1, che comunque, nel prossimo futuro potrebbe essere sostituita da ISO 8859-15 (ISO Latin 9), in cui si inserisce il simbolo dell’Euro al posto del simbolo di valuta generico. La tabella 224.2 mostra nel dettaglio la codifica ISO 8859-1. Si tenga presente che nel caso di ISO 8859-15, il punto di codifica 164 viene abbinato al simbolo dell’Euro. Tabella 224.2. ISO 8859-1. Ottale 2408 2418 2428 2438 2448 2458 2468 2478 2508 2518 2528 2538 2548 2558 2568 2578 2608 2618 2628 2638 2648 2658 2668 2678 2708 2718 2728 2738 2748 2758 2768 2778 3008 3018 3028 3038 3048 3058 3068 3078 3108 3118 3128 3138 3148 3158 Decimale 16010 16110 16210 16310 16410 16510 16610 16710 16810 16910 17010 17110 17210 17310 17410 17510 17610 17710 17810 17910 18010 18110 18210 18310 18410 18510 18610 18710 18810 18910 19010 19110 19210 19310 19410 19510 19610 19710 19810 19910 20010 20110 20210 20310 20410 20510 Esadecimale A016 A116 A216 A316 A416 A516 A616 A716 A816 A916 AA16 AB16 AC16 AD16 AE16 AF16 B016 B116 B216 B316 B416 B516 B616 B716 B816 B916 BA16 BB16 BC16 BD16 BE16 BF16 C016 C116 C216 C316 C416 C516 C616 C716 C816 C916 CA16 CB16 CC16 CD16 Carattere ¡ ¢ £ ¤ ¥ ¦ § ĺ © ª « ¬ ® ¯ ° ± 2 3 ’ µ ¶ . ¸ 1 º » ¼ ½ ¾ ¿ À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Denominazione in inglese NO-BREAK SPACE INVERTED EXCLAMATION MARK CENT SIGN POUND SIGN CURRENCY SIGN YEN SIGN BROKEN BAR SECTION SIGN DIAERESIS COPYRIGHT SIGN FEMININE ORDINAL INDICATOR LEFT-POINTING DOUBLE ANGLE QUOTATION MARK NOT SIGN SOFT HYPHEN REGISTERED SIGN MACRON DEGREE SIGN PLUS-MINUS SIGN SUPERSCRIPT TWO SUPERSCRIPT THREE ACUTE ACCENT MICRO SIGN PILCROW SIGN MIDDLE DOT CEDILLA SUPERSCRIPT ONE MASCULINE ORDINAL INDICATOR RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK VULGAR FRACTION ONE QUARTER VULGAR FRACTION ONE HALF VULGAR FRACTION THREE QUARTERS INVERTED QUESTION MARK LATIN CAPITAL LETTER A WITH GRAVE LATIN CAPITAL LETTER A WITH ACUTE LATIN CAPITAL LETTER A WITH CIRCUMFLEX LATIN CAPITAL LETTER A WITH TILDE LATIN CAPITAL LETTER A WITH DIAERESIS LATIN CAPITAL LETTER A WITH RING ABOVE LATIN CAPITAL LETTER AE LATIN CAPITAL LETTER C WITH CEDILLA LATIN CAPITAL LETTER E WITH GRAVE LATIN CAPITAL LETTER E WITH ACUTE LATIN CAPITAL LETTER E WITH CIRCUMFLEX LATIN CAPITAL LETTER E WITH DIAERESIS LATIN CAPITAL LETTER I WITH GRAVE LATIN CAPITAL LETTER I WITH ACUTE Esempi di codifica dei caratteri Ottale 3168 3178 3208 3218 3228 3238 3248 3258 3268 3278 3308 3318 3328 3338 3348 3358 3368 3378 3408 3418 3428 3438 3448 3458 3468 3478 3508 3518 3528 3538 3548 3558 3568 3578 3608 3618 3628 3638 3648 3658 3668 3678 3708 3718 3728 3738 3748 3758 3768 3778 Decimale 20610 20710 20810 20910 21010 21110 21210 21310 21410 21510 21610 21710 21810 21910 22010 22110 22210 22310 22410 22510 22610 22710 22810 22910 23010 23110 23210 23310 23410 23510 23610 23710 23810 23910 24010 24110 24210 24310 24410 24510 24610 24710 24810 24910 25010 25110 25210 25310 25410 25510 Esadecimale CE16 CF16 D016 D116 D216 D316 D416 D516 D616 D716 D816 D916 DA16 DB16 DC16 DD16 DE16 DF16 E016 E116 E216 E316 E416 E516 E616 E716 E816 E916 EA16 EB16 EC16 ED16 EE16 EF16 F016 F116 F216 F316 F416 F516 F616 F716 F816 F916 FA16 FB16 FC16 FD16 FE16 FF16 2409 Carattere Î Ï Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê ë ì í î ï ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý þ ÿ Denominazione in inglese LATIN CAPITAL LETTER I WITH CIRCUMFLEX LATIN CAPITAL LETTER I WITH DIAERESIS LATIN CAPITAL LETTER ETH LATIN CAPITAL LETTER N WITH TILDE LATIN CAPITAL LETTER O WITH GRAVE LATIN CAPITAL LETTER O WITH ACUTE LATIN CAPITAL LETTER O WITH CIRCUMFLEX LATIN CAPITAL LETTER O WITH TILDE LATIN CAPITAL LETTER O WITH DIAERESIS MULTIPLICATION SIGN LATIN CAPITAL LETTER O WITH STROKE LATIN CAPITAL LETTER U WITH GRAVE LATIN CAPITAL LETTER U WITH ACUTE LATIN CAPITAL LETTER U WITH CIRCUMFLEX LATIN CAPITAL LETTER U WITH DIAERESIS LATIN CAPITAL LETTER Y WITH ACUTE LATIN CAPITAL LETTER THORN LATIN SMALL LETTER SHARP S LATIN SMALL LETTER A WITH GRAVE LATIN SMALL LETTER A WITH ACUTE LATIN SMALL LETTER A WITH CIRCUMFLEX LATIN SMALL LETTER A WITH TILDE LATIN SMALL LETTER A WITH DIAERESIS LATIN SMALL LETTER A WITH RING ABOVE LATIN SMALL LETTER AE LATIN SMALL LETTER C WITH CEDILLA LATIN SMALL LETTER E WITH GRAVE LATIN SMALL LETTER E WITH ACUTE LATIN SMALL LETTER E WITH CIRCUMFLEX LATIN SMALL LETTER E WITH DIAERESIS LATIN SMALL LETTER I WITH GRAVE LATIN SMALL LETTER I WITH ACUTE LATIN SMALL LETTER I WITH CIRCUMFLEX LATIN SMALL LETTER I WITH DIAERESIS LATIN SMALL LETTER ETH LATIN SMALL LETTER N WITH TILDE LATIN SMALL LETTER O WITH GRAVE LATIN SMALL LETTER O WITH ACUTE LATIN SMALL LETTER O WITH CIRCUMFLEX LATIN SMALL LETTER O WITH TILDE LATIN SMALL LETTER O WITH DIAERESIS DIVISION SIGN LATIN SMALL LETTER O WITH STROKE LATIN SMALL LETTER U WITH GRAVE LATIN SMALL LETTER U WITH ACUTE LATIN SMALL LETTER U WITH CIRCUMFLEX LATIN SMALL LETTER U WITH DIAERESIS LATIN SMALL LETTER Y WITH ACUTE LATIN SMALL LETTER THORN LATIN SMALL LETTER Y WITH DIAERESIS Esempi di codifica dei caratteri 2410 224.3 Riferimenti • Jukka Korpela, A tutorial on character code issue <http://www.hut.fi/~jkorpela/chars.html> • Jukka Korpela, The ISO Latin 1 character repertoire - a description with usage and notes <http://www.hut.fi/~jkorpela/latin1/> • Roman Czyborra, The ISO 8859 Alphabet Soup <http://czyborra.com/charsets/iso8859.html> • Roman Czyborra, Codepages & Co. <http://czyborra.com/charsets/codepages.html> Appunti di informatica libera 2003.01.01 --- Copyright © 2000-2003 Daniele Giacomini -- daniele @ swlibero.org Parte xliii PostScript: un linguaggio per la composizione finale 225 Linguaggio PostScript: introduzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2412 225.1 Impostazione generale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2412 225.2 Linee e aree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2416 225.3 Salvare e recuperare le impostazioni grafiche . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2421 225.4 Spostamento del piano cartesiano e modifica della scala . . . . . . . . . . . . . . . . . . 2422 225.5 Ripetizione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2424 225.6 Testo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2424 225.7 Salvataggio e recupero delle impostazioni della pagina nel complesso . . . . . . 2426 225.8 Riferimenti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2427 226 PostScript: espressioni e funzioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2428 226.1 Lo stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2428 226.2 Funzioni comuni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2429 226.3 Operazioni sulle stringhe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2430 226.4 Funzioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2432 226.5 Dizionari . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2433 226.6 Riferimenti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2434 227 PostScript: caratteri da stampa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2435 227.1 Aspetto dei caratteri da stampa comuni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2436 227.2 Distorsione e spostamento dei caratteri da stampa . . . . . . . . . . . . . . . . . . . . . . . . 2439 227.3 Riferimenti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2441 228 Esempi di funzioni PostScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2443 228.1 Unità di misura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2443 228.2 Funzioni diagnostiche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2443 228.3 Gestione di stringhe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2444 228.4 Riferimenti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2446 2411 Capitolo 225 Linguaggio PostScript: introduzione Benché il linguaggio PostScript sia nato per le stampanti, disponendo di Ghostscript potrebbe essere usato anche per scrivere direttamente. Lo scopo di questo capitolo è quello di introdurre all’uso diretto del linguaggio PostScript, in modo molto semplice, facendo riferimento prevalentemente al livello 1, eventualmente con qualche annotazione sul livello 2, mentre il livello 3 diventa troppo complesso e non più utile per un utilizzo diretto. A ogni modo, gli esempi che si fanno sono stati verificati con Ghostscript e non con una vera stampante PostScript. 225.1 Impostazione generale Un file PostScript è un file di testo, in cui le righe sono terminate indifferentemente con <LF> oppure con <CR><LF>, che inizia con una riga simile al modello seguente: %!PS-Adobe-livello_ps [EPSF-livello_eps] Il livello è in pratica il numero di versione del linguaggio; per quanto riguarda il livello PostScript, si fa riferimento generalmente ai valori 1.0, 2.0 e 3.0. Il modello sintattico mostra la possibilità di aggiungere la stringa ‘EPSF-livello_eps’, con la quale si vuole specificare che si tratta di un file PostScript incapsulato. In altri termini, un file PostScript normale inizia più o meno come nell’esempio seguente, dove si fa riferimento al livello 2: %!PS-Adobe-2.0 In tal caso si intende lavorare su una serie di pagine; al contrario, se si sta realizzando una sola immagine nell’ambito di uno spazio determinato, si aggiunge la dichiarazione del tipo incapsulato: %!PS-Adobe-2.0 EPSF-1.2 In generale, il simbolo di percentuale (‘%’) serve a introdurre dei commenti che non generano un risultato nella stampa; tuttavia, una sequenza di due simboli di percentuale ha un ruolo speciale per la dichiarazione di direttive importanti; inoltre, la stessa dichiarazione iniziale del tipo di file è preceduta da un simbolo percentuale. In generale, onde evitare equivoci, si indica un commento con un solo simbolo di percentuale seguito da almeno uno spazio: % testo_commentato Il commento può essere piazzato ovunque, tenendo presente che vale dal punto in cui appare, fino alla fine della riga. Le direttive particolari che iniziano con due simboli di percentuale hanno la forma seguente: [ %%direttiva : argomenti ] In pratica, il nome delle direttive deve essere attaccato ai segni di percentuale; inoltre, se è prevista l’aggiunta di argomenti alla direttiva, dopo il nome della stessa appaiono due punti, seguiti da almeno uno spazio e dopo dagli argomenti previsti. Quello che segue è l’esempio di una struttura possibile per un file PostScript articolato su più pagine: 2412 Linguaggio PostScript: introduzione 2413 %!PS-Adobe-2.0 %%Creator: nome_del_redattore_del_file %%DocumentPaperSizes: formato %%EndComments %%BeginProlog prologo %%EndProlog %%Page: numero_mostrato pagina_reale istruzioni_ps showpage %%Page: numero_mostrato pagina_reale istruzioni_ps showpage ... %%Trailer %%EOF [ ] [ ] Il tutto dovrebbe essere abbastanza intuitivo: le prime istruzioni speciali, fino a ‘%%EndComments’, descrivono il documento specificando in particolare le dimensioni della pagina; le istruzioni racchiuse tra ‘%%BeginProlog’ e ‘%%EndProlog’ possono servire per dichiarare delle funzioni utilizzate nel documento; le istruzioni relative a ogni singola pagina sono introdotte da ‘%%Page: m n ’; la visualizzazione della pagina, dopo la sua costruzione, si ottiene con l’istruzione ‘showpage’; il file termina con ‘%%Trailer’ e ‘%%EOF’. A questo punto, conviene vedere subito come si può articolare un file PostScript che non contiene pagine, ma una sola immagine: %!PS-Adobe-2.0 EPSF-1.2 %%Creator: nome_del_redattore_del_file %%BoundingBox: 0 0 larghezza_in_punti altezza_in_punti %%EndComments %%BeginProlog prologo %%EndProlog istruzioni_ps showpage %%Trailer %%EOF [ ] Si può osservare che la direttiva speciale ‘%%BoundingBox’ va a sostituire ‘%%DocumentPaperSizes’, allo scopo di indicare l’area in cui vanno rappresentate le istruzioni. A ogni modo, la direttiva ‘%%BoundingBox’ può essere usata anche per un file PostScript diviso in pagine, quando si vuole indicare un formato non standard, oppure se si vuole essere precisi. 225.1.1 Piano di lavoro e unità di misura Il linguaggio PostScript è predisposto per fare riferimento a oggetti su un piano cartesiano ideale, in cui l’unità di misura normale è il punto tipografico, corrispondente secondo questo linguaggio a 1/72-esimo di pollice, pari a circa 0,35278 mm. In condizioni normali, la pagina è collocata sul piano cartesiano ideale come si vede nella figura 225.1, dove lo zero per x e y corrispondono esattamente con l’angolo inferiore sinistro; tuttavia, è consentita la definizione di pagine collocate in posizioni differenti, se questo può servire in qualche modo. Linguaggio PostScript: introduzione 2414 Figura 225.1. La pagina collocata su degli assi cartesiani ideali. y 788 x,y = 0,0 x,y = 595.3,788 595.3 x Gli oggetti grafici vengono disegnati sul piano cartesiano ideale; quello che risulta trovarsi sull’area della pagina potrà essere stampato. 225.1.2 Posizione corrente Il PostScript può essere visto come un linguaggio per disegnare (tracciare curve, riempire delle aree e piazzare dei caratteri tipografici). Tutto questo avviene quasi sempre indicando delle coordinate, dove spesso la posizione di partenza ha importanza. Le coordinate iniziali si modificano con l’istruzione ‘moveto’: x y moveto In pratica, si indicano due numeri, seguiti dalla parola chiave ‘moveto’. Il significato è molto semplice: il primo numero esprime la coordinata orizzontale (asse X), il secondo la coordinata verticale (asse Y). I valori si esprimono in punti tipografici. 225.1.3 Istruzioni speciali più importanti Le istruzioni più importanti che iniziano con due segni di percentuale sono elencate brevemente nella tabella 225.1. Tuttavia, è il caso di aggiungere qualche piccola indicazione a proposito di alcune di queste. Nessuna delle istruzioni che iniziano con due segni di percentuale è indispensabile; tuttavia alcune sono importanti. L’inserimento corretto di queste istruzioni rende il file PostScript più facile da gestire con gli strumenti comuni. Linguaggio PostScript: introduzione 2415 Tabella 225.1. Alcune istruzioni che iniziano con due segni di percentuale. Istruzione %%Creator: nome %%DocumentPaperSizes: formato %%BoundingBox: x 1 y 1 x 2 y 2 %%Title: titolo %%CreationDate: data %%Pages: n %%PageOrder: Ascend Descend %%EndComments %%BeginProlog %%EndProlog %%BeginSetup %%EndSetup %%Page: x n %%Trailer %%EOF | Descrizione Il nome del programma che ha composto il file. Formato della carta. Collocazione e dimensione della carta: da x 1 y 1 a x 2 y 2. Titolo del documento. Data e ora di creazione del documento. Quantità di pagine contenuta. Ordine di apparizione delle pagine: ascendente o discendente. Fine dell’intestazione con le informazioni generali. Inizia un’area di definizione delle funzioni. Termina l’area di definizione delle funzioni. Inizia un’area per l’inserimento di istruzioni di stampa. Termina l’area delle di istruzioni di stampa. Inizia la pagina n -esima, rappresentata come x . Conclude la serie delle pagine. Conclude definitivamente il file. L’istruzione ‘%%DocumentPaperSizes’ serve intuitivamente per elencare le dimensioni possibili delle pagine. In generale si indica una sola parola chiave che esprime sinteticamente la dimensione della pagina, come si vede nella tabella 225.2. Probabilmente non conviene andare al di fuori di pochi standard; eventualmente è preferibile indicare le coordinate esatte attraverso l’istruzione ‘%%BoundingBox’. Tabella 225.2. Formati di stampa comuni, indicabili come argomento dell’istruzione ‘%%DocumentPaperSizes’. Le dimensioni non sono necessariamente quelle reali, ma quelle conosciute dal linguaggio PostScript. formato letter legal a3 a4 a5 b4 b5 larghezza punti 612 612 842 595 421 709 501 altezza punti 792 1008 1190 842 595 1002 709 larghezza pollici 8,50 8,50 11,6944 8,26389 5,84722 9,84722 6,95833 altezza pollici 11,00 14,00 16,5278 11,6944 8,26389 13,9167 9,84722 larghezza cm 21,59 21,59 29,7 21 14,85 25,0119 17,6742 altezza cm 27,94 35,56 42 29,7 21 35,3483 25,0119 ‘%%BoundingBox’ consente di indicare la posizione dell’angolo inferiore sinistro e di quello su- periore destro della pagina. Di solito, le prime due coordinate che esprimono proprio la posizione dell’angolo inferiore sinistro, sono azzerate, a indicare che si parte dallo zero degli assi cartesiani ideali della superficie. 225.1.4 Aspetto delle istruzioni normali Le istruzioni PostScript sembrano non avere inizio e fine, perché si possono collocare su una o più righe indifferentemente, senza alcun segno di separazione. Per esempio, si può scrivere newpath 100 100 100 431 350 431 350 100 closepath moveto lineto lineto lineto oppure, indifferentemente Linguaggio PostScript: introduzione 2416 newpath 100 100 moveto 100 431 lineto 350 431 lineto 350 100 lineto closepath e in tanti altri modi intermedi. È evidente che se si vuole scrivere del codice intelligibile occorre uno stile (come in tutti i linguaggi di programmazione). la cosa che può apparire strana inizialmente è il fatto che i comandi che prevedono l’uso di argomenti, ricevono questi dati prima del nome del comando stesso. Per esempio, è già stata mostrata l’istruzione ‘moveto’, che riceve l’indicazione delle coordinate prima del suo nome. 225.2 Linee e aree La cosa più semplice che si può fare per cominciare a comprendere il linguaggio è quella di disegnare delle linee. In generale, il disegno avviene partendo dalle coordinate correnti, per cui questa indicazione non appare in modo esplicito, ma se necessario si definisce con uno spostamento attraverso l’istruzione ‘moveto’. Per le linee rette si possono usano le istruzioni ‘lineto’ e ‘rlineto’, dove la prima rappresenta un movimento con coordinate di destinazione assolute, mentre la seconda fa riferimento a coordinate di destinazione relative a quelle di partenza. Si osservino gli esempi seguenti, con cui si disegna lo stesso rettangolo largo 20 punti e alto 10 punti, a partire dalla coordinata x ,y=0,0: 0 0 20 20 0 0 10 10 0 0 0 0 20 0 -20 0 10 0 -10 0 moveto lineto lineto lineto lineto moveto rlineto rlineto rlineto rlineto In pratica, l’istruzione ‘lineto’ vuole l’indicazione del punto finale espresso come coordinata assoluta, mentre ‘rlineto’ vuole una coordinata relativa alla posizione corrente. x,y=0,10=+0,+10 x,y=20,10=+20,+0 x,y=0,0 x,y=20,0=+0-10 Il disegno non viene tracciato se alla fine non si aggiunge un’istruzione ‘stroke’, che non richiede argomenti. Dopo un’istruzione ‘stroke’ viene perduto il riferimento alle coordinate correnti, per cui, se necessario, si deve ricominciare con un’istruzione ‘moveto’. Si osservi l’esempio seguente, in cui lo stesso rettangolo viene disegnato un segmento alla volta, riposizionando sempre le coordinate iniziali: 0 0 0 20 20 20 20 0 0 10 10 10 10 0 0 0 moveto lineto moveto lineto moveto lineto moveto lineto stroke stroke stroke stroke Naturalmente, se si preferisce questo modo di utilizzo dell’istruzione ‘stroke’, si può anche cambiare un po’ lo stile di scrittura: Linguaggio PostScript: introduzione 0 0 20 20 0 10 10 0 moveto moveto moveto moveto 0 20 20 0 10 10 0 0 lineto lineto lineto lineto 2417 stroke stroke stroke stroke Le linee, oltre alla collocazione, hanno due caratteristiche importanti: lo spessore e il colore. Lo spessore predefinito dovrebbe essere di un punto, mentre il colore predefinito è il nero. Si modifica lo spessore delle linee con l’istruzione ‘setlinewidth’ e la colorazione (grigia) con l’istruzione ‘setgray’. Entrambi ricevono un solo argomento numerico, che nel primo caso esprime lo spessore della linea e nel secondo rappresenta la luminosità, con un valore che va da zero a uno (zero rappresenta il nero e uno rappresenta il bianco). Le istruzioni che alterano le caratteristiche delle linee, hanno effetto solo nel momento in cui appare l’istruzione ‘stroke’. In questo modo, si possono indicare le linee desiderate, quindi si possono cambiare le loro caratteristiche e infine si possono tracciare. L’esempio seguente disegna lo stesso rettangolo già presentato, specificando un tratto di due punti tipografici di colore grigio (esattamente a metà tra il bianco e il nero). Si può osservare che le istruzioni ‘setlinewidth’ e ‘setgray’ sono state collocate subito prima dell’istruzione ‘stroke’: 0 0 20 20 0 0 10 10 0 0 moveto lineto lineto lineto lineto 2 setlinewidth 0 setgray stroke Si possono tracciare delle linee per disegnare un poligono. L’esempio già visto rappresenta proprio un rettangolo, ma non è stato dichiarato esplicitamente il fatto che le linee devono congiungersi. Per farlo occorre dichiarare un percorso, con l’istruzione ‘newpath’, che si conclude con ‘closepath’. Si osservi la variante seguente al disegno del rettangolo: newpath 0 0 0 10 20 10 20 0 closepath moveto lineto lineto lineto 2 setlinewidth 0 setgray stroke In pratica, si tracciano le prime tre linee, mentre l’ultima viene indicata implicitamente con la richiesta di chiudere il percorso con l’istruzione ‘closepath’. Il fatto di avere realizzato un poligono, consente di definire il colore di riempimento. In condizioni normali, quando non è stato fissato alcunché, il poligono è trasparente, mentre se si fissa un riempimento diventa opaco e il colore ricopre anche il bordo tracciato con le linee.1 Il colore di riempimento si definisce con l’istruzione ‘fill’ e il colore usato è quello già fissato con l’istruzione ‘setgray’. newpath 0 1 0 moveto Il bordo ha lo stesso colore fissato con l’istruzione ‘setgray’, per cui tutto diventa dello stesso colore. Linguaggio PostScript: introduzione 2418 0 10 lineto 20 10 lineto 20 0 lineto closepath % 2 setlinewidth 0.5 setgray fill stroke L’esempio mostra l’utilizzo dell’istruzione ‘fill’ per colorare il rettangolo di grigio. Dal momento che lo spessore delle linee non serve più, l’istruzione relativa è stata commentata. Volendo mettere un bordo a questo rettangolo, occorre ridisegnarne sopra un altro trasparente, con il tratto desiderato: newpath 0 0 0 10 20 10 20 0 closepath moveto lineto lineto lineto 0.5 setgray fill stroke newpath 0 0 0 10 20 10 20 0 closepath 2 0 moveto lineto lineto lineto setlinewidth setgray stroke Per completare l’argomento sulle linee e sui poligoni, conviene mostrare un esempio completo, che poi viene mostrato nella figura 225.3. Si osservi che l’area in cui viene disegnato è lo stretto indispensabile per contenerlo: si estende da -1,-1 a 21,11, per dare lo spazio allo spessore della riga che è di due punti. %!PS-Adobe-2.0 EPSF-1.2 %%Creator: Daniele Giacomini %%BoundingBox: -1 -1 21 11 %%EndComments % Disegna un rettangolo newpath 0 0 0 10 20 10 20 0 closepath moveto lineto lineto lineto 0.5 setgray fill stroke newpath 0 0 0 10 20 10 20 0 closepath moveto lineto lineto lineto Linguaggio PostScript: introduzione 2 0 2419 setlinewidth setgray stroke showpage %%Trailer %%EOF Figura 225.3. Il rettangolo riempito e bordato. Il contorno è molto largo, ma è proporzionato rispetto al rettangolo che è alto solo 10 punti. 225.2.1 Archi e curve Si può disegnare un arco o un cerchio completo con l’istruzione ‘arc’. In questo caso, non c’è bisogno di fare riferimento a una posizione corrente; anzi, è meglio eliminare tale informazione con un’istruzione ‘stroke’ preventiva. L’istruzione ‘arc’ richiede l’indicazione delle coordinate del centro del cerchio, la lunghezza del raggio, l’angolo di partenza e l’angolo di destinazione in direzione antioraria. L’esempio seguente disegna un arco con centro nella posizione x ,y=100,150, con raggio di 50 punti, da 0 a 90 gradi: 100 150 50 0 90 arc In pratica, si tratta di quanto si vede nella figura 225.4. Figura 225.4. Arco di cerchio disegnato da 0 a 90 gradi. Se prima di disegnare il cerchio o l’arco di cerchio si tracciano altre linee, è conveniente chiudere i disegni precedenti con l’istruzione ‘stroke’, per evitare di avere delle coordinate correnti attive nel momento in cui si usa l’istruzione ‘arc’. Diversamente, si otterrebbe una linea che collega le coordinate iniziali con il punto di partenza dell’arco disegnato. Per disegnare un cerchio completo, basta indicare l’intervallo di angoli da 0 a 360 gradi. Se si vuole riempire il cerchio, non è necessario utilizzare le istruzioni ‘newpath’ e ‘closepath’, perché si ottiene sempre un riempimento, anche quando il cerchio non è completo. Il disegno di una curva è invece più complicato: si usa l’istruzione ‘curveto’, ma oltre alle coordinate di destinazione, bisogna indicare la tangente del punto di inizio e del punto di destinazione. Prima di dare altre spiegazioni, conviene partire da un esempio visivo, come si vede nella figura 225.5. La curva da prendere in considerazione è rappresentata con un tratto più scuro. Si possono vedere due linee oblique, che partono rispettivamente dal punto di inizio e dal punto di arrivo della curva: si tratta delle tangenti che stabiliscono la curvatura di partenza e di arrivo della linea disegnata. L’istruzione necessaria a disegnare questa curva è la seguente: Linguaggio PostScript: introduzione 2420 0 200 50 100 moveto 0 0 200 50 curveto Figura 225.5. Esempio di una curva in cui sono evidenti le tangenti. 100 50 0,0 200 In pratica: • le coordinate di partenza sono x ,y=0,50; • la prima tangente è la linea che va da x ,y=0,50 (le coordinate di partenza) a x ,y=200,100; • la seconda tangente è la linea che va da x ,y=200,50 (le coordinate di arrivo) a x ,y=0,0; • le coordinate di arrivo sono x ,y=200,50. Naturalmente, la lunghezza delle linee indicate come tangenti rendono più o meno importante la curvatura relativa. Si osservi, nella figura 225.6, come si trasforma il disegno se si accorcia la linea tangente di arrivo come nell’esempio seguente: 0 200 50 100 moveto 100 25 200 50 curveto Figura 225.6. Esempio di una curva in cui sono evidenti le tangenti. 100 50 25 0,0 100 200 Il modello sintattico per l’utilizzo dell’istruzione ‘curveto’ è quindi il seguente: x_tangente_inizio y_tangente_inizio x_tangente_fine y_tangente_fine x_fine_curva y_fine_curva curveto Linguaggio PostScript: introduzione 2421 225.3 Salvare e recuperare le impostazioni grafiche Le impostazioni grafiche, come quelle che si possono fissare con le istruzioni ‘setlinewidth’ e ‘setgray’, possono essere salvate e recuperate da una pila apposita. Si utilizza l’istruzione ‘gsave’ per salvare l’impostazione corrente e ‘grestore’ per recuperare le ultime impostazioni salvate. Si osservi l’esempio seguente: 1 setlinewidth gsave 2 setlinewidth gsave 4 setlinewidth 50 120 moveto 200 120 lineto stroke grestore 50 125 moveto 200 125 lineto stroke grestore 50 130 moveto 200 130 lineto stroke Vengono accumulate tre spessori differenti per le linee, quindi si procede disegnando tre linee, dopo ognuna delle quali viene recuperata l’ultima impostazione grafica. In pratica, la linea da 50,120 a 200,120 viene disegnata con un tratto di quattro punti; la linea da 50,125 a 200,125 viene disegnata con un tratto di tre punti; la linea da 50,130 a 200,130 viene disegnata con un tratto di un punto di spessore. Quando si disegna qualcosa, può essere opportuno racchiudere le modifiche alle caratteristiche entro una coppia ‘gsave’-‘grestore’, onde evitare di coinvolgere le impostazioni precedenti, che potrebbero riguardare il resto del file: gsave 4 setlinewidth 50 120 moveto 200 120 lineto stroke grestore Nell’esempio che appare sopra, si inizia salvando le impostazioni e impostando uno spessore di quattro punti. Viene quindi indicata la linea e fissata con l’istruzione ‘stroke’. Al termine si recuperano le impostazioni grafiche. Nello stesso modo, si potevano salvare e modificare le impostazioni grafiche subito prima dell’istruzione ‘stroke’: 50 120 moveto 200 120 lineto gsave 4 setlinewidth stroke grestore Attraverso la tecnica del salvataggio e del recupero delle caratteristiche grafiche, è possibile disegnare un poligono bordato senza dover ripetere due volte il tratto del contorno. In pratica, il comando di riempimento viene dato entro un ambiente protetto da ‘gsave’ e ‘grestore’, come si vede nell’esempio seguente: %!PS-Adobe-2.0 EPSF-1.2 %%Creator: Daniele Giacomini %%BoundingBox: -1 -1 21 11 %%EndComments Linguaggio PostScript: introduzione 2422 % Disegna un rettangolo newpath 0 0 0 10 20 10 20 0 closepath moveto lineto lineto lineto gsave 0.5 setgray fill grestore 2 setlinewidth 0 setgray stroke showpage %%Trailer %%EOF Il risultato è identico a quanto già visto nella figura 225.3. 225.4 Spostamento del piano cartesiano e modifica della scala È possibile spostare la posizione della superficie prima di dare altre istruzioni di scrittura di qualunque tipo. Si tratta in particolare delle istruzioni ‘translate’ e di ‘rotate’. La prima di queste due sposta le coordinate 0,0 in una posizione nuova, prendendo come riferimento le coordinate precedenti; la seconda ruota gli assi attorno alle coordinate 0,0. Per esempio, con le istruzioni 50 100 translate 50 50 moveto 100 50 lineto stroke si ottiene una linea orizzontale dalla posizione 100,150 alla posizione 150,150. Infatti, l’istruzione ‘translate’ sposta le coordinate 0,0 verso 50,100, secondo la collocazione precedente. La figura 225.7 mostra la collocazione iniziale e lo spostamento; la linea disegnata è quella che appare con tratto più scuro. Figura 225.7. Esempio riferito a uno spostamento degli assi. 150 100 0,0 50 0,0 50 50 100 100 150 Linguaggio PostScript: introduzione 2423 L’istruzione ‘rotate’ fa ruotare il piano cartesiano sul centro delle coordinate 0,0. La figura 225.8 mostra cosa accade se si sposta lo zero nella posizione 0,0 e poi si ruota di 30 gradi, con le istruzioni seguenti: 50 30 50 100 stroke 50 translate rotate 50 50 moveto lineto Figura 225.8. Esempio riferito a uno spostamento e a una rotazione degli assi. 0 10 50 50 50 0,0 0,0 50 Lo spostamento e la rotazione del piano sono informazioni che possono essere salvate e recuperate con le istruzioni ‘gsave’ e ‘grestore’. Pertanto, prima di uno spostamento o di una rotazione, conviene salvare la situazione, per recuperarla quando questi cambiamenti non servono più. gsave 50 30 50 translate rotate 50 50 100 50 stroke grestore moveto lineto Oltre allo spostamento e alla rotazione del piano, si può modificare la scala, con l’istruzione ‘scale’. Gli argomenti dell’istruzione sono due valori, che esprimono il rapporto nei confronti dell’asse X e nei confronti dell’asse Y. Dopo la modifica della scala, le coordinate 0,0 rimangono centrate sulla stessa posizione iniziale. Per esempio, 1 0.5 scale serve a fare in modo che la scala dell’asse Y risulti schiacciata alla metà del valore precedente, mentre l’asse X non viene modificato. Anche le alterazioni della scala possono essere recuperate da un’istruzione ‘grestore’. Linguaggio PostScript: introduzione 2424 225.5 Ripetizione Un gruppo di istruzioni, racchiuso tra parentesi graffe, può essere ripetuto più volte con l’istruzione ‘repeat’: n {istruzioni } repeat Evidentemente, perché ciò abbia un senso, è necessario che le istruzioni da ripetere creino ogni volta un cambiamento, come una rotazione o uno spostamento di assi. Per esempio, 36 {10 rotate 10 10 moveto 30 30 lineto} repeat stroke Disegna una stellina attorno alle coordinate 0,0, con un diametro di 80 punti. In questo caso, la rotazione riporta alla fine gli assi nella posizione di partenza, ma in generale conviene salvare e ripristinare la situazione: gsave 36 {10 rotate 10 10 moveto 30 30 lineto} repeat stroke grestore Figura 225.9. Esempio di un disegno ottenuto con la rotazione. 225.6 Testo Per poter scrivere sulla superficie del foglio, è necessario selezionare il tipo di carattere e la dimensione prima di tutto. Questo si ottiene con alcune istruzioni, che in pratica conviene usare assieme: /carattere findfont dimensione scalefont setfont Per esempio, per usare il carattere Helvetica alto 12 punti, si usa l’istruzione seguente: /Helvetica findfont 12 scalefont setfont La scrittura vera e propria avviene con l’istruzione ‘show’, con la quale si colloca il testo a partire dalle coordinate correnti, per cui si fa precedere normalmente da un’istruzione ‘moveto’: (testo) show Come si vede dal modello sintattico, il testo deve essere scritto tra parentesi tonde e collocato prima della parola chiave ‘show’. Dovendo usare le parentesi tonde per delimitare il testo da visualizzare, deve esserci un modo per poter togliere a queste il valore sintattico normale, quando c’è la necessità di rappresentarle nel testo. In pratica si usano le sequenze ‘\(’ e ‘\)’ per rappresentarle; inoltre, dal momento che la barra obliqua inversa ha un significato speciale, per rappresentare questa si usa la sequenza ‘\\’. Linguaggio PostScript: introduzione 2425 La tabella 225.3 riepiloga le sequenze speciali più importanti per il testo delimitato tra parentesi tonde. Tabella 225.3. Alcune sequenze speciali per la scrittura di testo delimitato da parentesi tonde, con l’istruzione ‘show’. Sequenza \\ \( \) \nnn Descrizione Barra obliqua inversa. Parentesi tonda aperta. Parentesi tonda chiusa. Simbolo corrispondente al numero, in ottale, secondo la codifica attuale. Se si seleziona un carattere non disponibile, viene utilizzato il Courier. La tabella 225.4 elenca i nomi standard dei tipi di carattere fondamentali che si possono utilizzare con il linguaggio PostScript. Tabella 225.4. Nomi dei tipi di carattere comuni che possono essere utilizzati con il linguaggio PostScript. Nome Times, Times-Roman Times-Italic Times-Bold Times-BoldItalic Helvetica Helvetica-Oblique Helvetica-Bold Helvetica-BoldOblique Courier Courier-Oblique Courier-Bold Courier-BoldOblique Symbol Descrizione Times normale. Times corsivo. Times neretto. Times neretto inclinato. Helvetica normale. Helvetica inclinato. Helvetica neretto. Helvetica neretto inclinato. Courier normale. Courier inclinato. Courier neretto. Courier neretto inclinato. Symbol. Un’istruzione simile a ‘show’, si occupa di visualizzare il testo, controllandone lo spostamento in corrispondenza di un simbolo particolare: x y n (testo) widthshow L’istruzione ‘widthshow’ serve a fissare uno spostamento orizzontale (x ) e uno spostamento verticale (y), subito dopo il simbolo corrispondente al numero n . In pratica, se alla fine di ogni spazio si vuole aggiungere uno spazio orizzontale di due punti, si usa la forma seguente: 2 0 32 (testo) widthshow Questa è anche la situazione tipica, in cui si vuole allargare lo spazio tra le parole, per adattare la riga scritta alla larghezza disponibile. Naturalmente, lo spazio normale può anche essere ridotto, se lo si desidera, utilizzando valori orizzontali negativi, come nell’esempio seguente: -1 0 32 (testo) widthshow Se si attribuisce un valore anche al secondo argomento numerico, si ottiene uno spostamento verticale, come nell’esempio seguente, in cui ogni parola viene alzata di due punti rispetto alla precedente: 0 2 32 (testo) widthshow Linguaggio PostScript: introduzione 2426 225.7 Salvataggio e recupero delle impostazioni della pagina nel complesso Quando si scrive un documento composto da diverse pagine, diventa utile la possibilità di recuperare le impostazioni precedenti, prima di passare alla pagina successiva. È già stata presentata la coppia di istruzioni ‘gsave’ e ‘grestore’, specifica per le impostazioni grafiche. Per tutto, si può usare invece la coppia ‘save’ e ‘restore’. Di solito si inizia una pagina con ‘save’ e si conclude con ‘restore’, in modo da garantire il recupero di tutto, senza dimenticare qualcosa. %!PS-Adobe-2.0 %%Creator: nome_del_redattore_del_file %%DocumentPaperSizes: formato %%EndComments %%BeginProlog prologo %%EndProlog %%Page: numero_mostrato pagina_reale save istruzioni_ps showpage restore %%Page: numero_mostrato pagina_reale save istruzioni_ps showpage restore ... %%Trailer %%EOF [ ] [ ] Le istruzioni ‘save’ e ‘restore’ dovrebbero essere sempre annidate correttamente, nel senso che ogni istruzione ‘restore’ va a recuperare l’ultima istruzione ‘save’ che non sia già stata presa in considerazione da un altro ‘restore’. Se viene eseguito un ‘restore’ che non risulta abbinato a un’istruzione ‘save’, si genera un errore irreversibile. Per ovviare all’inconveniente di dover seguire attentamente l’uso delle istruzioni ‘save’ e ‘restore’, si può attribuire un «nome» a un’istruzione ‘save’, richiamando lo stesso nome nel momento del ‘restore’: /nome save def ... ... ... nome restore La cosa non è molto intuitiva, ma funziona così: il nome che viene dichiarato nel momento dell’uso dell’istruzione ‘save’, viene posto davanti all’istruzione ‘restore’. Se nello spazio tra queste due istruzioni apparivano altre istruzioni ‘save’, queste sono tutte annullate. Segue un esempio: /Mia_Configurazione_Predefinita save def ... ... ... Mia_Configurazione_Predefinita restore Linguaggio PostScript: introduzione 2427 Tabella 225.5. Tabella riassuntiva delle istruzioni più semplici del linguaggio PostScript. Istruzione x y moveto x y rmoveto x y lineto x y rlineto x y m n o arc x y m n o arcn x y x y x y curveto x y translate n rotate n {istruzioni } repeat n setlinewidth n setgray fill newpath closepath stroke gsave grestore save restore /nome save def nome restore /nome findfont dim scalefont setfont (testo) show x y n (testo) widthshow x 0 32 (testo) widthshow Descrizione Cambia le coordinate correnti senza disegnare. Cambia le coordinate correnti in modo relativo. Traccia una linea fino alle coordinate assolute indicate. Traccia una linea fino alle coordinate relative indicate. Arco con centro in x ,y, raggio m , da n a o gradi, in senso antiorario. Arco con centro in x ,y, raggio m , da n a o gradi, in senso orario. Curva indicando le coordinate di arrivo delle tangenti e infine della curva. Fa sì che x ,y corrispondano alle nuove coordinate 0,0. Ruota di n il fondo, con centro sulle coordinate 0,0. Ripete n volte le istruzioni tra parentesi graffe. Spessore delle linee. Colorazione grigia: 0=nero; 1=bianco. Riempie i poligoni e le aree racchiuse entro le curve. Inizia a disegnare un oggetto nuovo. Unisce l’ultimo punto disegnato con il punto di partenza. Fissa le linee tracciate. Accumula le impostazioni grafiche. Recupera le impostazioni. Accumula tutte le impostazioni della pagina. Recupera le impostazioni della pagina. Accumula tutte le impostazioni dichiarando un nome. Recupera le impostazioni riferite a quel nome. Seleziona il carattere e la dimensione indicata. Scrive il testo indicato usando il carattere già stabilito. Scrive il testo indicato con uno spostamento x ,y alla fine del simbolo n . Scrive il testo indicato con l’aggiunta di uno spazio di x tra le parole. 225.8 Riferimenti • Cappella Archive <http://www.cappella.demon.co.uk/index.html> • David Byram-Wigfield, Practical PostScript <http://www.cappella.demon.co.uk/bookpdfs/pracpost.pdf> • David Byram-Wigfield, Making an electronic book <http://www.cappella.demon.co.uk/tinypdfs/06ebook.pdf> • Paul Bourke, PostScript Tutorial <http://astronomy.swin.edu.au/pbourke/dataformats/postscript/> • First Guide to PostScript <http://www.cs.indiana.edu/docproject/programming/postscript/postscript.html> • Portable Document Format Reference Manual, 1999 <http://partners.adobe.com/asn/developer/acrosdk/docs/pdfspec.pdf> Appunti di informatica libera 2003.01.01 --- Copyright © 2000-2003 Daniele Giacomini -- daniele @ swlibero.org Capitolo 226 PostScript: espressioni e funzioni Il linguaggio PostScript è nato per essere interpretato in modo veloce da stampanti realizzate appositamente. In questo senso, la sua logica segue vagamente quella di un linguaggio assemblatore. 226.1 Lo stack Per poter scrivere codice PostScript un po’ più complesso, diventa necessario l’utilizzo di istruzioni che realizzano delle espressioni, fino ad arrivare alla costruzione di funzioni (procedure) che possono essere richiamate successivamente. Purtroppo, le espressioni realizzate con questo linguaggio, diventano un po’ complicate da leggere. Infatti, queste funzioni ricevono i loro argomenti prelevandoli da uno stack (pila) ed emettono risultati inserendoli nello stesso stack. dato ... funzione Osservando il modello, le informazioni che non sono riconducibili a nomi di funzione, vengono inserite in questo stack, che poi la prima funzione inizia a leggere. Si osservi l’istruzione seguente: 1 2 3 4 5 6 7 8 9 moveto lineto I valori da uno a nove, vengono inseriti così come sono nello stack, poi ogni funzione preleva dallo stack la quantità di argomenti che la riguarda. In questo caso, ‘moveto’ preleva gli ultimi due valori a essere stati inseriti, precisamente la coppia otto e nove, per cui sposterà le coordinate correnti in 8,9; successivamente è il turno di ‘lineto’, che preleva altri due valori, precisamente il sei e il sette, tracciando una linea fino al punto 6,7. Pertanto, tutto è come se fosse stato scritto nel modo seguente: 8 9 moveto 6 7 lineto Tuttavia, rimangono ancora altri valori nello stack, per altre funzioni successive, ammesso che vogliano usarli, perché se si inseriscono altri valori, questi vengono poi estratti per primi. Dato questo meccanismo, diventano importanti alcune funzioni che consentono di intervenire su questo stack: ‘clear’ svuota completamente lo stack; ‘pop’ preleva ed elimina l’ultimo valore inserito.1 Sono un po’ più difficili da comprendere le funzioni ‘exch’ e ‘roll’. La prima scambia l’ordine degli ultimi due valori inseriti nello stack; la seconda esegue uno scorrimento, verso sinistra o verso destra di una certa quantità di questi valori: n_elementi_da_scorrere scorrimento roll Per esempio, se nello stack ci fossero i valori 1, 2, 3, 4, 5, 6 e 7, in questo ordine, per cui il primo a essere prelevato sarebbe il numero 7, l’istruzione ‘3 2 roll’ trasformerebbe questa sequenza in 1, 2, 3, 4, 6, 7 e 5; al contrario, l’istruzione ‘3 -2 roll’ trasformerebbe questa sequenza in 1, 2, 3, 4, 7, 5 e 6. In pratica, il primo valore indica quanti elementi prendere in considerazione, a partire dall’ultimo, mentre il secondo indica quante volte scorrere e in quale direzione. Figura 226.1. Esempio di funzionamento dell’istruzione ‘roll’, con uno scorrimento verso destra. stack iniziale: 3 2 roll stack finale: 1 2 3 4 5 6 7 7 5 6 6 7 5 1 2 3 4 6 7 5 1 (primo scorrimento verso destra) (secondo scorrimento verso destra) A fianco di ‘pop’ si potrebbe immaginare la presenza di una funzione con il nome push, ma in questo caso non serve, perché l’azione di inserimento nello stack avviene in modo implicito. 2428 PostScript: espressioni e funzioni 2429 Figura 226.2. Esempio di funzionamento dell’istruzione ‘roll’, con uno scorrimento verso sinistra. stack iniziale: 1 2 3 4 5 6 7 3 -2 roll 6 7 5 7 5 6 1 2 3 4 7 5 6 stack finale: (primo scorrimento verso sinistra) (secondo scorrimento verso sinistra) Quando una funzione restituisce un valore, lo fa inserendolo implicitamente nello stack. In questo modo, l’assegnamento a una variabile, così come si è abituati nei linguaggi di programmazione comuni, non c’è. Al massimo si definisce una funzione che restituisce un valore, inserendolo nello stack. A questo punto si può cominciare a comprendere che i dati inseriti nello stack, quando ciò non avviene per mezzo di una funzione che restituisce qualcosa, devono avere una rappresentazione formale. Può trattarsi di: valori numerici, che si scrivono come sono, utilizzando il punto per separare la parte decimale; stringhe, che sono delimitate da parentesi tonde e possono contenere delle sequenze di escape; espressioni, che sono delimitate tra parentesi graffe (si ricordi il caso della funzione ‘repeat’). I valori logici, Vero e Falso, non hanno una rappresentazione particolare e si indicano espressamente solo attraverso le funzioni ‘true’ e ‘false’. Tabella 226.1. Rappresentazione dei dati e gestione dello stack. Istruzione intero .decimale (stringa ) {espressione } clear oggetto pop oggetto_1 oggetto_2 exch m n roll oggetto dup [ ] Descrizione Inserisce il valore numerico nello stack. Inserisce la stringa nello stack. Inserisce le istruzioni nello stack. Svuota lo stack. Preleva dallo stack l’ultimo valore inserito. Scambia gli ultimi due valori nello stack. Fa scorrere gli ultimi m elementi dello stack di n posizioni. Preleva l’ultimo valore e ne inserisce due copie nello stack. 226.2 Funzioni comuni Alcune funzioni operano su valori numerici, restituendo un risultato che, secondo la logica del linguaggio PostScript, viene inserito nello stack. Per esempio, la funzione ‘add’ riceve due valori restituendo la somma di questi: 10 20 add 40 moveto In questo caso, vengono sommati i valori 10 e 20, inserendo nello stack il valore 30. Così, si ottiene lo spostamento nelle coordinate 30,40, attraverso la funzione ‘moveto’. I valori logici, come accennato, si indicano attraverso le funzioni ‘true’ e ‘false’, che si limitano rispettivamente a inserire nello stack il valore corrispondente. Possono generare risultati logici anche alcune funzioni di confronto e i valori logici possono essere rielaborati attraverso funzioni booleane. Infine, in base a un valore logico è possibile eseguire o meno un gruppo di espressioni. Si osservino gli esempi seguenti. • 10 20 lt La funzione ‘lt’ confronta due valori e restituisce Vero se il primo (secondo la lettura umana) è minore. In questo caso, viene restituito Vero. • 10 20 lt 45 34 gt and PostScript: espressioni e funzioni 2430 La funzione ‘and’ restituisce Vero se riceve due valori Vero simultaneamente. In questo caso, la funzione ‘lt’ inserisce il valore Vero nello stack e anche la funzione ‘gt’ inserisce un altro valore Vero, dal momento che il confrontando i valori 45 e 34 si vede che il primo è maggiore del secondo. • 10 20 lt {45 50 moveto} if La funzione ‘if’ preleva un valore logico e un gruppo di istruzioni. Se il valore logico è Vero viene eseguito il raggruppamento di istruzioni. In questo caso, dato che la funzione ‘lt’ inserisce il valore Vero nello stack, così può essere eseguito lo spostamento nelle coordinate 45,50. • 10 20 lt {45 50 moveto} {50 45} moveto ifelse La funzione ‘ifelse’ preleva un valore logico e due gruppi di istruzioni. Se il valore logico è Vero viene eseguito il primo gruppo di istruzioni, altrimenti viene eseguito il secondo. In questo caso, dato che la funzione ‘lt’ inserisce il valore Vero nello stack, così viene eseguito lo spostamento nelle coordinate 45,50. Queste funzioni vengono descritte brevemente nella tabella 226.2. Tabella 226.2. Espressioni matematiche, logiche e condizionali. Istruzione n neg m n add m n sub m n mul m n div m n mod n round n abs n sin n cos m n min m n max true false m n gt m n ge m n lt m n le m n eq m n ne bool {istruzioni } if bool {istr_1} {istr_2} ifelse Descrizione Inverte il segno del valore. Somma i due valori. Sottrae n da m . Moltiplica i valori. Divide m per n . Il resto della divisione intera di m per n . Arrotonda n . Calcola il valore assoluto di n . Calcola il seno di n . Calcola il coseno di n . Restituisce il minimo tra due valori. Restituisce il massimo tra due valori. Vero. Falso. Vero se m è maggiore di n . Vero se m è maggiore o uguale a n . Vero se m è minore di n . Vero se m è minore o uguale a n . Vero se i valori sono uguali. Vero se i valori sono diversi. Esegue le istruzioni se il valore logico è Vero. Esegue il primo o il secondo gruppo di istruzioni in base al valore logico. 226.3 Operazioni sulle stringhe A causa della struttura del linguaggio, la gestione delle stringhe non è affatto intuitiva: bisogna tradurre tutto nell’ottica dello stack. Tanto per cominciare, la cosa più semplice che si può fare con una stringa è misurarne la lunghezza con l’aiuto della funzione ‘stringwidth’. Per la precisione, si tratta di determinare la posizione finale di una stringa collocata a partire dalle coordinate 0,0: stringa stringwidth PostScript: espressioni e funzioni 2431 Se si osserva la figura 226.3, si può vedere la stringa composta dalla parola «Ciao», scritta con il carattere Helvetica, avente un corpo di 12 punti. Come si vede, la sua lunghezza è di 24,672 punti. Figura 226.3. Lunghezza di una stringa. 0,0 Ciao 24.672 Quando c’è la necessità di convertire un valore in una stringa, si pone il problema dell’allocazione di memoria per la stringa stessa. Per esempio, la funzione ‘cvs’ converte un valore in stringa, ma per farlo deve avere già una stringa da prelevare dallo stack: valore stringa cvs Volendo convertire il valore 23,45 in stringa, bisogna preparare prima una stringa di almeno cinque caratteri: 23.45 ( ) cvs Per allocare una stringa, composta da caratteri <NUL>, ovvero 0008, si può usare la funzione ‘string’, che richiede l’indicazione della quantità di caratteri. Pertanto, la stessa cosa avrebbe potuto essere scritta nel modo seguente: 23.45 5 string cvs Naturalmente, la funzione ‘cvs’ si può usare per visualizzare la stringa generata, per esempio nel modo seguente: 10 10 moveto 23.45 5 string cvs show Si osservi che con ‘cvs’, anche se si alloca una stringa più grande del necessario, questa viene ridotta alla dimensione richiesta dalla conversione. Tabella 226.3. Espressioni relative a stringhe. Istruzione n string stringa stringwidth valore stringa cvs Descrizione Alloca una string di n caratteri <NUL>. Inserisce le coordinate finali della stringa nello stack. Restituisce una stringa corrispondente al valore. 2432 PostScript: espressioni e funzioni 226.4 Funzioni Una funzione si definisce attraverso la sintassi seguente: /nome {istruzioni } def In pratica, si vuole fare in modo che usando il nome indicato, si faccia riferimento automaticamente al gruppo di istruzioni contenuto tra parentesi graffe.2 Come per qualunque altra funzione normale, anche le funzioni definite in questo modo ricevono gli argomenti della chiamate dallo stack. Per esempio, la funzione ‘quadrilatero’ che si potrebbe dichiarare nel modo seguente, /quadrilatero { newpath moveto lineto lineto lineto closepath stroke } def va usata mettendo davanti, ordinatamente gli argomenti per le varie funzioni utilizzate. Per esempio, volendo disegnare un quadrato con gli angoli nelle coordinate 0,0, 0,10, 10,10 e 10,0, si dovrà usare la funzione ‘quadrilatero’ nel modo seguente: 10 0 10 10 0 10 0 0 rettangolo È importante osservare che la prima coppia di coordinate è quella presa in considerazione dall’ultima funzione ‘lineto’ contenuta nel raggruppamento di ‘quadrilatero’. Così come si definisce una funzione, si può attribuire a un nome un valore costante. In questi casi eccezionali, è consentito l’eliminazione delle parentesi graffe: /nome costante def Con la definizione di costanti, si può stabilire una volta per tutte il valore di qualcosa, come nell’esempio seguente: /Margine_Sinistro 80 def /Margine_Destro 80 def /Margine_Superiore 100 def /Margine_Inferiore 100 def 226.4.1 Variabili Nel linguaggio PostScript non è prevista la gestione di variabili: tutto viene elaborato attraverso lo stack. Tuttavia, esiste un trucco per ottenere qualcosa che assomigli a delle variabili; si tratta di sfruttare opportunamente la definizione di funzioni. È già stato visto l’assegnamento di un valore costante a un nome: /nome costante def oppure: /nome { costante } def Se si vuole attribuire a una funzione un valore diverso, occorre un trucco, che si può schematizzare come segue: /nome_1 { /nome_2 exch def } def Si tratta di una funzione che ne dichiara un’altra, ma si osservi con attenzione: la parola chiave ‘exch’ non è racchiusa tra parentesi graffe e non può esserlo, se si vuole che il meccanismo funzioni. Per assegnare un valore alla funzione nome_2 , si utilizza una chiamata alla funzione nome_1 : 2 Eccezionalmente, se si tratta di definire una costante o se si vuole ridefinire il nome di un’altra funzione, non sono necessarie le parentesi graffe. PostScript: espressioni e funzioni 2433 n nome_1 Per leggere il valore, si fa riferimento alla funzione nome_2 , come nell’esempio seguente in cui si utilizza questo dato come coordinata Y per uno spostamento: n nome_1 m nome_2 moveto 226.5 Dizionari La dichiarazione delle funzioni può essere inserita in un dizionario, da richiamare quando serve e da sostituire eventualmente con altre di un altro dizionario, quando la situazione lo richiede. In pratica, la definizione di dizionari di funzioni consente di fare riferimento a gruppi di funzioni solo nell’ambito di un certo contesto, ripristinando un utilizzo differente delle stesse subito dopo. /dizionario n dict def dizionario begin dichiarazione_di_funzione ... ... end Il modello sintattico mostra in che modo procedere alla dichiarazione di un dizionario. Si può osservare che prima della parola chiave ‘dict’ occorre indicare un numero, allo scopo di definire una quantità di memoria da allocare per il dizionario stesso. Per abilitare l’uso delle funzioni dichiarate nel dizionario, si deve dichiarare espressamente: dizionario begin istruzione ... ... end Eventualmente, la dichiarazione di utilizzo di un dizionario si può annidare; quando si raggiunge la parola chiave ‘end’, termina il campo di azione dell’ultimo dizionario ancora aperto. In generale, potrebbe essere conveniente inserire la dichiarazione dei dizionari nell’ambito delle istruzioni speciali ‘%%BeginProlog’ e ‘%%EndProlog’. L’esempio seguente mostra un estratto di un file PostScript ipotetico, in cui si dichiara un dizionario (molto breve) e lo si utilizza immediatamente nell’ambito della pagina (i puntini di sospensione indicano una parte mancante del file che non viene mostrata). %!PS-Adobe-2.0 %%DocumentPaperSizes: a4 %%EndComments %%BeginProlog /Mio_Dizionario 50 dict def Mio_Dizionario begin /quadrilatero { newpath moveto lineto lineto lineto closepath stroke } def /Margine_Sinistro 80 def /Margine_Destro 80 def /Margine_Superiore 100 def /Margine_Inferiore 100 def end % Fine della dichiarazione del dizionario «Mio_Dizionario» %%EndProlog Mio_Dizionario begin %%Page: 1 1 ... ... ... PostScript: espressioni e funzioni 2434 showpage %%Page: 2 2 ... ... ... showpage end % Fine del campo di azione del dizionario «Mio_Dizionario» %%Trailer %%EOF 226.6 Riferimenti • Cappella Archive <http://www.cappella.demon.co.uk/index.html> • David Byram-Wigfield, Practical PostScript <http://www.cappella.demon.co.uk/bookpdfs/pracpost.pdf> • Paul Bourke, PostScript Tutorial <http://astronomy.swin.edu.au/pbourke/dataformats/postscript/> • David Byram-Wigfield, Making an electronic book <http://www.cappella.demon.co.uk/tinypdfs/06ebook.pdf> • First Guide to PostScript <http://www.cs.indiana.edu/docproject/programming/postscript/postscript.html> Appunti di informatica libera 2003.01.01 --- Copyright © 2000-2003 Daniele Giacomini -- daniele @ swlibero.org Capitolo 227 PostScript: caratteri da stampa Il linguaggio PostScript, nelle sue prime versioni, prevede che il file contenente le istruzioni sia di tipo ASCII, dove è ammissibile usare gli 8 bit per esteso. Tuttavia, l’insieme di caratteri a disposizione non è il solito ISO 8859-1, ma qualcosa di diverso che può essere visto nella tabella 227.1. Tabella 227.1. Insieme di caratteri normale del linguaggio PostScript. * * * \037 \000 \040 \100 \140 ! " # $ % & ’ ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ‘ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ \200 \240 \300 \340 \077 \137 \177 \237 ¡ ¢ £ ⁄ ¥ ƒ § ¤ ' “ « ‹ › fi fl – † ‡ · ¶ • ‚ „ ” » … ‰ ` ´ ˆ ˜ ¯ ˘ ˙ ¨ ˚ ¸ ˝ ˛ ˇ — Æ ª Ł Ø Œ º æ ı ł ø œ ß ¿ \277 \337 \377 Per fare riferimento a un simbolo in forma numerica, basta indicare il numero ottale corrispondente, di tre cifre, preceduto dalla barra obliqua inversa. Per facilitare la lettura, la tabella mostra questo modo di fare riferimento ai caratteri, all’inizio e alla fine di ogni riga. Per poter usare la codifica corrispondente allo standard ISO 8859-1, è necessario dare delle istruzioni particolari. Volendo sbirciare nel codice PostScript generato da vari sistemi di composizione, si potrà osservare che ognuno utilizza un proprio modo, più o meno sofisticato. Probabilmente, la tecnica più semplice è quella che si può leggere nei sorgenti di Ghostscript, dove vengono dichiarate due funzioni apposite nel modo seguente: /font-to-iso-latin-1 { dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall /Encoding ISOLatin1Encoding def currentdict end dup /FontName get 80 string cvs (-ISOLatin1) concatstrings cvn exch definefont } def /find-latin-font { findfont font-to-iso-latin-1 } def In questo modo, quando si va a dichiarare l’uso di un certo tipo di carattere da stampa, invece dell’istruzione /carattere findfont dimensione scalefont setfont si userà piuttosto la forma seguente: /carattere find-latin-font dimensione scalefont setfont 2435 PostScript: caratteri da stampa 2436 227.1 Aspetto dei caratteri da stampa comuni Il linguaggio PostScript mette a disposizione pochi tipi di carattere da stampa; tuttavia, è disponibile l’interprete Ghostscript, su moltissime piattaforme, che mette a disposizione un numero discreto di questi tipi. La tabella 227.13 elenca brevemente i nomi di questi tipi di carattere, mentre in altre tabelle successive viene mostrato l’aspetto di alcuni di questi, ordinando i simboli secondo l’insieme ISO 8859-1. Tabella 227.2. Carattere da stampa AvantGarde. * * * \037 \000 \040 \100 \140 \200 \240 \300 \340 ! " # $ % & ’ ( ) * + , − . / 0 1 2 @ A B C D E F G H I J K L M N O P Q R ‘ a b c d e f g h i j k l mn o p q r ı ` ´ ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ - ® ¯ ° ± ² À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò à á â ã ä å æ ç è é ê ë ì 3 S s ˆ ³ Ó 4 T t ˜ ´ Ô 5 U u ¯ µ Õ 6 V v ˘ ¶ Ö 7 W w ˙ · × 8 X x ¨ ¸ Ø ø 9 : Y Z y z ˚ ¹ º Ù Ú ú ; [ { ¸ » Û < = > \ ] ^ | } ~ ˝ ˛ ¼ ½ ¾ Ü Ý Þ 8 X x ¨ ¸ Ø ø 9 : Y Z y z ˚ ¹ º Ù Ú ú ; [ { ¸ » Û 8 X x ¨ ¸ Ø ø 9 : ; < Y Z [ \ y z { | ˚ ¸ ¹ º » ¼ Ù Ú Û Ü ú ? _ \077 \137 \177 ˇ ¿ ß \237 \277 \337 \377 Tabella 227.3. Carattere da stampa Bookman. * * * \037 \000 \040 \100 \140 \200 \240 \300 \340 ! " # $ % & ’ ( ) * + , − . / 0 1 2 @ A B C D E F G H I J K L M N O P Q R ‘ a b c d e f g h i j k l mn o p q r ı ` ´ ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ - ® ¯ ° ± ² À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò à á â ã ä å æ ç è é ê ë ì 3 S s ˆ ³ Ó 4 T t ˜ ´ Ô 5 U u ¯ µ Õ 6 V v ˘ ¶ Ö 7 W w ˙ · × < = > \ ] ^ | } ~ ˝ ˛ ¼ ½ ¾ Ü Ý Þ ? _ \077 \137 \177 ˇ ¿ ß \237 \277 \337 \377 Tabella 227.4. Carattere da stampa Courier. * * * \037 \000 \040 \100 \140 \200 \240 \300 \340 ! " # $ % & ’ ( ) * + , − . / 0 @ A B C D E F G H I J K L M N O P ‘ a b c d e f g h i j k l m n o p ı ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ - ® ¯ ° À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð à á â ã ä å æ ç è é ê ë ì 1 Q q ` ± Ñ 2 R r ´ ² Ò 3 S s ˆ ³ Ó 4 T t ˜ ´ Ô 5 U u ¯ µ Õ 6 V v ˘ ¶ Ö 7 W w ˙ · × = ] } ˝ ½ Ý > ^ ~ ˛ ¾ Þ ? _ \077 \137 \177 ˇ ¿ ß \237 \277 \337 \377 Tabella 227.5. Carattere da stampa Helvetica. * * * \037 \000 \040 \100 \140 \200 \240 \300 \340 ! " # $ % & ’ ( ) @A B C D E F G H I ‘ a b c d e f g h i * + , − . / 0 1 2 J K L M N O P Q R j k l m n o p q r ı ` ´ ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ - ® ¯ ° ± ² À Á Â Ã Ä Å ÆÇ È É Ê Ë Ì Í Î Ï Ð Ñ Ò à á â ã ä å æ ç è é ê ë ì 3 S s ˆ ³ Ó 4 T t ˜ ´ Ô 5 U u ¯ µ Õ 6 V v ˘ ¶ Ö 7 W w ˙ · × 8 X x ¨ ¸ Ø ø 9 : Y Z y z ˚ ¹ º Ù Ú ú ; [ { ¸ » Û < = > \ ] ^ | } ~ ˝ ˛ ¼ ½ ¾ Ü Ý Þ ? _ \077 \137 \177 ˇ ¿ ß \237 \277 \337 \377 PostScript: caratteri da stampa 2437 Tabella 227.6. Carattere da stampa NewCenturySchlbk. * * * \037 \000 \040 \100 \140 \200 \240 \300 \340 ! " # $ % & ’ ( ) * + , − . / 0 1 2 @ A B C D E F G H I J K L MN O P Q R ‘ a b c d e f g h i j k l m n o p q r ı ` ´ ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ - ® ¯ ° ± ² À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò à á â ã ä å æ ç è é ê ë ì 3 S s ˆ ³ Ó 4 T t ˜ ´ Ô 5 U u ¯ µ Õ 6 V v ˘ ¶ Ö 7 W w ˙ · × 8 X x ¨ ¸ Ø ø 9 : Y Z y z ˚ ¹ º Ù Ú ú ; [ { ¸ » Û < = > \ ] ^ | } ~ ˝ ˛ ¼ ½ ¾ Ü Ý Þ 8 X x ¨ ¸ Ø ø 9 : Y Z y z ˚ ¹ º Ù Ú ú ; [ { ¸ » Û 8 X x ¨ ¸ Ø ø 9 : Y Z y z ˚ ¹ º Ù Ú ú ; [ { ¸ » Û 8 X x ¨ ¸ Ø ø 9 : ; < Y Z [ \ y z { | ˚ ¸ ¹ º » ¼ Ù Ú Û Ü ú ? _ \077 \137 \177 ˇ ¿ ß \237 \277 \337 \377 Tabella 227.7. Carattere da stampa Palatino. * * * \037 \000 \040 \100 \140 \200 \240 \300 \340 ! " # $ % & ’ ( ) * + , − . / 0 1 2 @ A B C D E F G H I J K L MN O P Q R ‘ a b c d e f g h i j k l m n o p q r ı ` ´ ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ - ® ¯ ° ± ² À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò à á â ã ä å æ ç è é ê ë ì 3 S s ˆ ³ Ó 4 T t ˜ ´ Ô 5 U u ¯ µ Õ 6 V v ˘ ¶ Ö 7 W w ˙ · × < = > \ ] ^ | } ~ ˝ ˛ ¼ ½ ¾ Ü Ý Þ ? _ \077 \137 \177 ˇ ¿ ß \237 \277 \337 \377 Tabella 227.8. Carattere da stampa Times. * * * \037 \000 \040 \100 \140 \200 \240 \300 \340 ! " # $ % & ’ ( ) @ A B C D E F G H I ‘ a b c d e f g h i * + , − . / 0 1 2 J K L M N O P Q R j k l m n o p q r ı ` ´ ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ - ® ¯ ° ± ² À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò à á â ã ä å æ ç è é ê ë ì 3 S s ˆ ³ Ó 4 T t ˜ ´ Ô 5 U u ¯ µ Õ 6 V v ˘ ¶ Ö 7 W w ˙ · × < = > \ ] ^ | } ~ ˝ ˛ ¼ ½ ¾ Ü Ý Þ ? _ \077 \137 \177 ˇ ¿ ß \237 \277 \337 \377 Tabella 227.9. Carattere da stampa Utopia. * * * \037 \000 \040 \100 \140 \200 \240 \300 \340 ! " # $ % & ’ ( ) * + , − . / 0 @ A B C D E F G H I J K L M N O P ‘ a b c d e f g h i j k l m n o p ı ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ - ® ¯ ° À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð à á â ã ä å æ ç è é ê ë ì 1 Q q ` ± Ñ 2 R r ´ ² Ò 3 S s ˆ ³ Ó 4 T t ˜ ´ Ô 5 U u ¯ µ Õ 6 V v ˘ ¶ Ö 7 W w ˙ · × = ] } ˝ ½ Ý > ^ ~ ˛ ¾ Þ ? _ \077 \137 \177 ˇ ¿ ß \237 \277 \337 \377 PostScript: caratteri da stampa 2438 Tabella 227.10. Carattere da stampa ZapfChancery. * * * \037 \000 \040 \100 \140 \200 \240 \300 \340 ! " # $ % & ’ ( ) * + , − . / 0 1 2 @ A B C D E F G H I J K L M N O P Q R ‘ a b c d e f g h i j k l m n o p q r ı ` ´ ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ - ® ¯ ° ± ² À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò à á â ã ä å æ ç è é ê ë ì 3 S s ˆ ³ Ó 4 T t ˜ ´ Ô 5 U u ¯ µ Õ 6 V v ˘ ¶ Ö 7 W w ˙ · × 8 X x ¨ ¸ Ø ø 9 : Y Z y z ˚ ¹ º Ù Ú ú ; [ { ¸ » Û < = > \ ] ^ | } ~ ˝ ˛ ¼ ½ ¾ Ü Ý Þ ? _ \077 \137 \177 ˇ ¿ ß \237 \277 \337 \377 Tabella 227.11. Carattere da stampa ZapfDingbats (solo con l’insieme di caratteri normale). * * * \037 \000 \040 \100 \140 ✁✂✃✄☎ ✆ ✇ ✈ ✉ ☛☞✌ ✍ ✎ ✏ ✐ ✑✒✓ ✔ ✕ ✖ ✗ ✘ ✙ ✚ ✛ ✜ ✝ ✞ ✟ ✠ ✡ ✢ ✣ ✤ ✥ ✦ ✧ ★ ✩ ✪ ✫ ✬ ✭ ✮ ✯ ✰ ✱ ✲ ✳ ✴ ✵ ✶ ✷ ✸ ✹ ✺ ✻ ✼ ✽ ✾ ✿ ❀ ❁ ❂ ❃ ❄ ❅ ❆ ❇ ❈ ❉ ❊ ❋ ● ❍ ■ ❏ ❐ ❑ ❒ ▲ ▼ ◆ ❖ ◗ ❘ ❙ ❚ ❛ ❜ ❝ ❞ \200 \240 \300 \340 \077 \137 \177 \237 ❡ ❢ ❣ ❤ ❥ ❦ ❧ ♣ ♦ ♥ ♠ ① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ❶ ❷ ❸ ❹ ❺ ❻ ❼ ❽ ❾ ❿ ➀ ➁ ➂ ➃ ➄ ➅ ➆ ➇ ➈ ➉ ➊ ➋ ➌ ➍ ➎ ➏ ➐ ➑ ➒ ➓ ➔ → ↔↕ ➘ ➙ ➚ ➛ ➜ ➝ ➞ ➟ ➠ ➡ ➢ ➣ ➤ ➥ ➦ ➧ ➨ ➩ ➪ ➫ ➬ ➭ ➮ ➯ ➱ ➲ ➳➴ ➵ ➶ ➷ ➸➹ ➺ ➻ ➼ ➽➾ \277 \337 \377 Tabella 227.12. Carattere da stampa Symbol (solo con l’insieme di caratteri normale). * * * \037 \000 \040 \100 \140 ! ∀ # ∃ % & ∋ ( ) ≅ Α Β Χ ∆ Ε Φ Γ Η Ι α β χ δ ε φ γ η ι ∗ + , − . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? ϑ Κ Λ Μ Ν Ο Π Θ Ρ Σ Τ Υ ς Ω Ξ Ψ Ζ [ ∴ ] ⊥ _ ϕ κ λ µ ν ο π θ ρ σ τ υ ϖ ω ξ ψ ζ { | } ∼ \200 \240 \300 \340 \077 \137 \177 \237 ϒ ′ ≤ ⁄ ∞ ƒ ♣ ♦ ♥ ♠ ↔←↑ →↓ ° ± ″ ≥ × ∝ ∂ • ÷ ≠ ≡ ≈ … ↵ ℵ ℑ ℜ ℘⊗ ⊕ ∅ ∩ ∪ ⊃ ⊇ ⊄ ⊂ ⊆ ∈ ∉ ∠ ∇ ∏ √ ⋅ ¬ ∧ ∨ ⇔⇐⇑ ⇒⇓ ◊ 〈 ∑ 〉 ∫ ⌠ ⌡ Tabella 227.13. Nomi dei tipi di carattere da stampa che solitamente sono disponibili con Ghostscript. Nome AvantGarde-Book AvantGarde-BookOblique AvantGarde-Demi AvantGarde-DemiOblique Bookman-Demi Bookman-DemiItalic Bookman-Light Bookman-LightItalic Courier Courier-Bold Courier-BoldOblique Courier-Oblique Helvetica Helvetica-Bold Helvetica-BoldOblique Helvetica-Narrow Helvetica-Narrow-Bold Descrizione AvantGarde normale. AvantGarde inclinato. AvantGarde neretto. AvantGarde neretto obliquo. Bookman neretto. Bookman neretto corsivo. Bookman normale. Bookman corsivo. Courier normale. Courier neretto. Courier neretto inclinato. Courier inclinato. Helvetica normale. Helvetica neretto. Helvetica neretto inclinato. Helvetica stretto. Helvetica stretto neretto. \277 \337 \377 PostScript: caratteri da stampa Nome Helvetica-Narrow-BoldOblique Helvetica-Narrow-Oblique Helvetica-Oblique NewCenturySchlbk-BoldItalic NewCenturySchlbk-Bold NewCenturySchlbk-Italic NewCenturySchlbk-Roman Palatino-Bold Palatino-BoldItalic Palatino-Italic Palatino-Roman Times-Bold Times-BoldItalic Times-Italic Times-Roman ZapfChancery-MediumItalic ZapfDingbats Symbol 2439 Descrizione Helvetica stretto neretto inclinato. Helvetica stretto inclinato. Helvetica inclinato. NewCenturySchlbk neretto corsivo. NewCenturySchlbk neretto. NewCenturySchlbk corsivo. NewCenturySchlbk normale. Palatino neretto. Palatino neretto corsivo. Palatino corsivo. Palatino normale. Times neretto. Times neretto inclinato. Times corsivo. Times normale. ZapfChancery-MediumItalic medio corsivo. ZapfDingbats (solo con l’insieme di caratteri normale). Symbol (solo con l’insieme di caratteri normale). 227.2 Distorsione e spostamento dei caratteri da stampa Fino a questo punto è stato visto come selezionare un carattere da stampa con l’istruzione /carattere findfont dimensione scalefont setfont oppure con quella seguente, nel caso sia disponibile la funzione relativa: /carattere find-latin-font dimensione scalefont setfont In alternativa, è possibile sostituire l’indicazione della dimensione con qualcosa di più articolato, secondo uno dei due schemi seguenti: /carattere findfont [dim_x rot_x rot_y dim_y sp_x sp_y ] makefont setfont /carattere find-latin-font [dim_x rot_x rot_y dim_y sp_x sp_y ] makefont setfont Tra parentesi quadre appaiono una serie di valori, che se non utilizzati vanno lasciati azzerati. Per comprenderne il significato, conviene partire dalla situazione normale. Supponendo di volere dichiarare un carattere da stampa di tipo Helvetica, normale, di 12 punti, si può usare la definizione solita /Helvetica findfont 12 scalefont setfont oppure, in modo più complesso, quella seguente: /Helvetica findfont [12 0 0 12 0 0] makefont setfont In pratica, dim_x e dim_y servono per definire la dimensione orizzontale e verticale del carattere. In condizioni normali, la dimensione è la stessa; diversamente, con una dimensione orizzontale più grande di quella verticale si ottiene un carattere più largo, mentre con una dimensione verticale maggiore di quella orizzontale, si ottiene un carattere alto (o sottile). Si osservi l’esempio seguente, di un carattere Helvetica allargato e successivamente alzato. Il risultato, in rapporto, si può vedere nella figura 227.1. /Helvetica findfont [30 0 0 12 0 0] makefont setfont /Helvetica findfont [12 0 0 30 0 0] makefont setfont PostScript: caratteri da stampa 2440 Figura 227.1. Distorsione orizzontale e verticale del carattere da stampa. Helvetica allargato Helvetica alzato (stretto) I valori corrispondenti a rot_x e rot_y permettono di inclinare l’asse X o l’asse Y del testo. In pratica, modificando rot_x si cambia l’andamento orizzontale del testo secondo l’angolo indicato. Per esempio un angolo di 10 gradi farà sì che la riga scritta sia inclinata verso l’alto (ovvero di 10 gradi in senso antiorario), mentre un angolo di -10 gradi genererà una riga inclinata verso il basso. La figura 227.2 mostra il risultato che si può ottenere con le due distorsioni seguenti: /Helvetica findfont [12 10 0 12 0 0] makefont setfont /Helvetica findfont [12 -10 0 12 0 0] makefont setfont Figura 227.2. Distorsione dell’inclinazione orizzontale. te ra n ce s a n de tu rit c S S cr itt u ra di sc en de nt e Intervenendo invece nel valore rot_y, si cambia l’inclinazione del carattere, senza cambiare l’andamento della riga. In pratica, valori positivi dell’angolazione generano un’inclinazione in avanti, simile a un corsivo, mentre valori negativi generano un’inclinazione all’indietro. La figura 227.3 mostra il risultato che si può ottenere con le due distorsioni seguenti: /Helvetica findfont [12 0 10 12 0 0] makefont setfont /Helvetica findfont [12 0 -10 12 0 0] makefont setfont PostScript: caratteri da stampa 2441 Figura 227.3. Distorsione dell’inclinazione verticale. Inclinato in avanti Inclinato all’indietro I valori corrispondenti a sp_x e sp_y rappresentano uno spostamento orizzontale e verticale, in punti, senza applicare delle distorsioni vere e proprie. L’andamento del testo, che normalmente si svolge da sinistra a destra, può essere invertito, assegnando un valore negativo per il primo valore, ovvero per dim_x . La figura 227.4 mostra la comparazione tra un testo scritto in modo normale e un altro che invece si sviluppa verso sinistra, con un comando simile a quello seguente: /Helvetica findfont [-12 0 0 12 0 0] makefont setfont Figura 227.4. Scrittura normale e scrittura da destra a sinistra. Andamento normale otitrevni otnemadnA Così come si può invertire l’andamento del testo in orizzontale, si può invertire in modo verticale, ottenendo una sorta di riflessione. La figure 227.5 mette a confronto un testo scritto in modo normale e un altro modificato con l’istruzione seguente: /Helvetica findfont [12 0 0 -12 0 0] makefont setfont Figura 227.5. Scrittura ruotata sull’asse orizzontale. Scrittura normale Scrittura riflessa 227.3 Riferimenti • Cappella Archive <http://www.cappella.demon.co.uk/index.html> • David Byram-Wigfield, Practical PostScript <http://www.cappella.demon.co.uk/bookpdfs/pracpost.pdf> • Paul Bourke, PostScript Tutorial <http://astronomy.swin.edu.au/pbourke/dataformats/postscript/> PostScript: caratteri da stampa 2442 • David Byram-Wigfield, Making an electronic book <http://www.cappella.demon.co.uk/tinypdfs/06ebook.pdf> • First Guide to PostScript <http://www.cs.indiana.edu/docproject/programming/postscript/postscript.html> Appunti di informatica libera 2003.01.01 --- Copyright © 2000-2003 Daniele Giacomini -- daniele @ swlibero.org Capitolo 228 Esempi di funzioni PostScript In questo capitolo si raccolgono alcuni esempi di funzioni PostScript che possono essere utili a vario titolo. Trattandosi di un linguaggio specifico per la stampa, non vengono proposti esempi di programmazione standard. 228.1 Unità di misura L’unità di misura utilizzata è sempre il punto tipografico, che in questo ambito corrisponde a 1/72-esimo di pollice, ovvero a 0,3527777 mm (per converso, un millimetro è pari a 2,834646 punti). Volendo usare unità di misura più comuni, si possono realizzare alcune funzioni molto semplici che si limitano a moltiplicare il valore per una costante, in modo da ottenere come risultato l’equivalente in punti: /cm /mm /pt /in { { { { 28.346456 mul } def 2.8346456 mul } def 1 mul } def 72 mul } def % % % % <n> <n> <n> <n> cm mm pt in % % % % converte centimetri in punti converte millimetri in punti non converte alcunché converte pollici in punti In questo modo, al posto di inserire un valore puro e semplice, basta aggiungere subito dopo la sigla dell’unità di misura, che in realtà è una funzione. Per esempio: 3 cm 18 cm moveto Evidentemente, la funzione ‘pt’ è inutile, ma può servire per mantenere coerenza con il resto, nel momento in cui si utilizzi sistematicamente questo meccanismo per indicare le coordinate o le distanze. 228.2 Funzioni diagnostiche Pur non trattandosi di un linguaggio di programmazione normale, quando si cerca di realizzare qualcosa di particolare, può essere comoda la possibilità di mostrare un valore da qualche parte, per verificare il contenuto di una data informazione. /diag_display_number % <n> <x> <y> diag_display_number { gsave /Helvetica findfont 10 scalefont setfont moveto 100 string cvs show grestore } def La funzione appena mostrata, serve per ottenere la conversione di un numero in stringa, che poi viene visualizzato nelle coordinate previste. Andrebbe usata nel modo seguente, dove x ,y sono le coordinate a partire dalle quali mostrare il valore: n x y diag_display_number Dal momento che questa funzione preleva il valore dallo stack, potrebbe essere conveniente la duplicazione di tale valore prima di utilizzarlo: n dup x y diag_display_number Volendo completare il problema con una funzione equivalente per la visualizzazione delle stringhe, basta la variante seguente: /diag_display_string % <stringa> <x> <y> diag_display_string { 2443 Esempi di funzioni PostScript 2444 gsave /Helvetica findfont 10 scalefont setfont moveto show grestore } def 228.3 Gestione di stringhe Quando si disegnano delle figure o dei grafici, può essere comodo disporre di qualche funzione che faciliti la collocazione di didascalie o di annotazioni di qualunque tipo. Qui viene proposto un sistema molto semplice, con cui è possibile piazzare delle stringhe allineate correttamente a sinistra, a destra o al centro, date le coordinate di riferimento. Si parte con la definizione di alcune «variabili», che servono per fissare i punti di riferimento delle stringhe: /set_line_t /set_line_l /set_line_r /set_line_c /set_line_h { { { { { /line_t /line_l /line_r /line_c /line_h exch exch exch exch exch def def def def def } } } } } def def def def def La funzione ‘line_t’ verrà usata per conoscere la posizione verticale (Y) della stringa da collocare; la funzione ‘line_l’ servirà per fornire la posizione iniziale (X) di una stringa da allineare a sinistra; ‘line_r’ fornirà la posizione finale (X) di una stringa da allineare a destra; ‘line_c’ fornirà la posizione centrale (X) di una stringa da centrare; infine, ‘line_h’ servirà per conoscere la distanza tra le righe. Per usare le funzioni che verranno presentate, dovranno essere impostati inizialmente i valori per le variabili appena descritte. Per esempio, sapendo che si vuole scrivere un testo allineato a sinistra a partire dalla coordinata 100,50, con una distanza tra le righe di 14 punti, basterà impostare i valori nel modo seguente: 50 set_line_t 100 set_line_l 14 set_line_h Dal momento che non si devono centrare le righe e nemmeno allineare a destra, le altre variabili non servono, altrimenti occorrerebbe impostare ‘line_c’ o ‘line_r’, al posto di ‘line_l’. /show_line_left % <stringa> show_line_left { % Si posiziona all’inizio della riga. line_l line_t moveto % Mostra la riga. show % Sottrae alla posizione Y l’altezza della riga. line_t line_h sub set_line_t } def Si osservi la funzione ‘show_line_left’: si usano i valori restituiti dalle funzioni ‘line_l’ e ‘line_t’ per impostare le coordinate iniziali, quindi si visualizza la stringa. Subito dopo si provvede a ridurre il valore della variabile corrispondente alla funzione ‘line_t’ del valore restituito da ‘line_h’ (la distanza tra le righe), in modo da poter continuare con la visualizzazione di altre stringhe, con lo stesso allineamento sinistro, subito sotto quella appena inserita. /show_line_right % <stringa> show_line_right { % Calcola la lunghezza della riga. dup % fa una copia della stringa stringwidth % restituisce le coordinate finali X e Y Esempi di funzioni PostScript 2445 pop % elimina la coordinata Y % Sottrae dalla posizione destra la lunghezza della riga, % cambiando poi il segno. line_r sub neg % Si posiziona correttamente. line_t moveto % Mostra la riga e va all’inizio di una riga nuova. show % Sottrae alla posizione Y l’altezza della riga. line_t line_h sub set_line_t } def La funzione ‘show_line_right’ è molto simile, con la differenza che occorre fare qualche calcolo per individuare la posizione orizzontale di inizio, sapendo la posizione finale ottenuta dalla funzione ‘line_r’. Per questo, viene fatta una copia della stringa, che quindi viene misurata con la funzione ‘setlinewidth’. Da questa misurazione si espelle l’informazione verticale, che risulta inutile, sottraendo poi a questa il valore restituito da ‘line_r’. Quello che si ottiene è la distanza dalla posizione destra finale, con segno invertito, pertanto si inverte nuovamente con la funzione ‘neg’. Disponendo della coordinata X, si aggiunge la coordinata Y, data da ‘line_t’, spostando la posizione corrente, per poi mostrare la stringa e infine preparare nuovamente la posizione verticale per una nuova riga. /show_line_center { % Calcola la lunghezza della riga. dup % fa una copia della stringa stringwidth % restituisce le coordinate finali X e Y pop % elimina la coordinata Y 2 div % divide la lunghezza a metà % Sottrae dal centro la metà della riga, cambiando poi il segno. line_c sub neg % Si posiziona correttamente. line_t moveto % Mostra la riga e va all’inizio di una riga nuova. show % Sottrae alla posizione Y l’altezza della riga. line_t line_h sub set_line_t } def La funzione ‘show_line_center’ centra la stringa in riferimento alla posizione ‘line_c’. I calcoli sono simili a quelli per l’allineamento a destra, con la differenza che la distanza dal centro è pari alla metà della lunghezza della stringa. Il resto è equivalente. L’esempio seguente mostra come scrivere qualcosa con queste funzioni; la figura 228.1 mostra il risultato che si ottiene osservando il riquadro che va da 0,0 a 150,100: /Times-Roman findfont 10 scalefont setfont 90 10 140 75 14 set_line_t set_line_l set_line_r set_line_c set_line_h (Stringa a sinistra) show_line_left (Stringa centrata) show_line_center (Stringa a destra) show_line_right Esempi di funzioni PostScript 2446 (Ciao) show_line_center () show_line_center (:-\)) show_line_center showpage Figura 228.1. Esempio nell’uso delle funzioni sulle stringhe. Stringa a sinistra Stringa centrata Stringa a destra Ciao :-) Naturalmente, si possono predisporre anche delle abbreviazioni a queste funzioni: /L { show_line_left } def /R { show_line_right } def /C { show_line_center } def In questo modo, l’indicazione delle stringhe può essere ridotto alla forma seguente: (Stringa a sinistra) L (Stringa centrata) C (Stringa a destra) R (Ciao) C () C (:-\)) C 228.4 Riferimenti • Cappella Archive <http://www.cappella.demon.co.uk/index.html> • David Byram-Wigfield, Practical PostScript <http://www.cappella.demon.co.uk/bookpdfs/pracpost.pdf> • David Byram-Wigfield, The TinyDict Typesetter <http://www.cappella.demon.co.uk/tinyfiles/tinydict.html> • David Byram-Wigfield, Tinydict <http://www.cappella.demon.co.uk/tinyfiles/tinydict.ps> • David Byram-Wigfield, Making an electronic book <http://www.cappella.demon.co.uk/tinypdfs/06ebook.pdf> • First Guide to PostScript <http://www.cs.indiana.edu/docproject/programming/postscript/postscript.html> Esempi di funzioni PostScript Appunti di informatica libera 2003.01.01 --- Copyright © 2000-2003 Daniele Giacomini -- daniele @ swlibero.org 2447 2448 Esempi di funzioni PostScript Parte xliv TeX 229 teTeX: la distribuzione Unix di TeX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2453 229.1 Collocazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2453 229.2 Configurazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2454 229.3 Funzionamento fondamentale di TeX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2457 229.4 Interazione con TeX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2460 229.5 Riferimenti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2463 230 TeX: introduzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2464 230.1 Elementi essenziali del linguaggio TeX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2464 230.2 Variabili e tipi di dati . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2468 230.3 Dichiarazione di macroistruzioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2475 230.4 Riferimenti ad altre parole o simboli di controllo . . . . . . . . . . . . . . . . . . . . . . . . . 2478 230.5 Testo normale e ambienti matematici . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2479 230.6 Modalità orizzontale e modalità verticale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2479 230.7 Strutture di controllo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2480 230.8 Verifica del significato di un’istruzione elementare . . . . . . . . . . . . . . . . . . . . . . . 2481 230.9 Riferimenti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2482 231 TeX: caratteri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2483 231.1 Caratteri speciali . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2483 231.2 Accenti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2484 231.3 Apici, trattini e legati automatici . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2485 231.4 Istruzioni alternative per generare simboli particolari . . . . . . . . . . . . . . . . . . . . . 2486 231.5 Caratteri da stampa standard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2487 231.6 Sottolineatura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2490 232 TeX: la pagina . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2492 232.1 La parte centrale della pagina . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2492 232.2 Intestazione e fondo pagina . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2495 232.3 Numerazione delle pagine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2496 232.4 Note a piè di pagina . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2496 232.5 Oggetti fluttuanti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2497 233 TeX: paragrafi, righe, spazi, scatole e linee . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2498 233.1 Caratteristiche normali di un paragrafo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2498 233.2 Spaziatura orizzontale automatica e separazione automatica dei paragrafi in righe 2500 2449 233.3 Rientri particolari . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2501 233.4 Paragrafi etichettati . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2503 233.5 Attuazione dei comandi riferiti ai paragrafi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2504 233.6 Tolleranza estetica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2505 233.7 Sillabazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2506 233.8 Spaziature verticali . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2507 233.9 Righe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2510 233.10 Spazi orizzontali . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2512 233.11 Spazio rigido . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2514 233.12 Scatole . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2514 233.13 Linee guida . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2518 233.14 Linee . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2519 233.15 Scatole più complesse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2520 234 TeX: tabelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2522 234.1 Tabulazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2522 234.2 Tabelle più complesse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2527 235 TeX: ambienti matematici . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2532 235.1 Due situazioni differenti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2532 235.2 Spazi orizzontali . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2533 235.3 Caratteri e simboli . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2533 235.4 Dimensione del testo matematico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2539 235.5 Punteggiatura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2540 235.6 Frazioni e simili . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2540 235.7 Apici e pedici . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2541 235.8 Radici . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2542 235.9 Sottolineature e sopralineature . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2542 235.10 Funzioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2543 235.11 Delimitatori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2544 235.12 Matrici e sistemi di equazioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2545 235.13 Dichiarazione di teoremi e corollari . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2547 235.14 Equazioni in evidenza . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2548 236 LaTeX: introduzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2550 236.1 Comandi e modelli sintattici . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2550 236.2 Esempio iniziale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2551 236.3 Struttura essenziale di un documento LaTeX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2554 236.4 Composizione per approssimazione successiva . . . . . . . . . . . . . . . . . . . . . . . . . . . 2556 236.5 Personalizzazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2557 236.6 Localizzazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2559 236.7 Variabili e tipi di dati . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2562 2450 236.8 Riferimenti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2566 237 LaTeX: struttura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2568 237.1 Dichiarazione dello stile generale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2568 237.2 Preambolo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2569 237.3 Inizio e fine del documento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2569 237.4 Suddivisione del documento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2570 237.5 Ambienti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2573 238 LaTeX: la pagina . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2575 238.1 Dimensioni della pagina . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2575 238.2 Flusso verticale del testo, colonne e salti pagina . . . . . . . . . . . . . . . . . . . . . . . . . . 2576 238.3 Stile della pagina . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2580 238.4 Numerazione delle pagine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2581 238.5 Note a piè di pagina . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2581 238.6 Sillabazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2582 239 LaTeX: caratteri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2583 239.1 Caratteri che hanno un significato speciale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2583 239.2 Corpi uniformi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2584 239.3 Caratteri da stampa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2585 239.4 Definizione dettagliata del carattere da stampa . . . . . . . . . . . . . . . . . . . . . . . . . . . 2587 239.5 Linee e cornicette attorno al testo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2588 239.6 Spostamento verticale del testo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2589 240 LaTeX: blocchi di testo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2590 240.1 Caratteristiche normali di un paragrafo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2590 240.2 Allineamento del testo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2591 240.3 Elenchi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2592 240.4 Citazioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2597 240.5 Versi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2598 240.6 Testo letterale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2599 240.7 Ambienti fluttuanti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2600 241 LaTeX: spazi e scatole . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2603 241.1 Spazi orizzontali . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2603 241.2 Spazi verticali . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2604 241.3 Elasticità controllabile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2606 241.4 Interlinea . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2606 241.5 Scatole . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2607 241.6 Testo da salvare e da recuperare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2610 241.7 Linee . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2611 2451 242 LaTeX: riferimenti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2613 242.1 Indice generale, indice delle tabelle e delle figure . . . . . . . . . . . . . . . . . . . . . . . . 2613 242.2 Riferimenti liberi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2616 242.3 Indice analitico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2617 242.4 Bibliografie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2621 243 LaTeX: tabelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2624 243.1 Tabella fatta di tabulazioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2624 243.2 Tabella fatta di colonne e righe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2628 243.3 Tabella a cavallo di più pagine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2633 244 LaTeX: figure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2635 244.1 Disegnare con LaTeX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2635 244.2 Importazione di file EPS esterni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2639 245 LaTeX: ambienti matematici . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2641 245.1 Definizione della modalità matematica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2641 245.2 Spazi orizzontali e punteggiatura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2642 245.3 Caratteri e simboli . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2643 245.4 Delimitatori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2649 245.5 Modifica delle caratteristiche del carattere . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2650 245.6 Espressioni varie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2650 245.7 Matrici e sistemi di equazioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2652 245.8 Teoremi, corollari e dichiarazioni simili . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2654 246 LaTeX: file esterni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2658 246.1 Importazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2658 246.2 Importazione letterale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2658 246.3 Creazione di file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2658 2452 Capitolo 229 teTeX: la distribuzione Unix di TeX TeX è un linguaggio di programmazione per l’editoria elettronica. Come nei linguaggi di programmazione comuni è possibile realizzare procedure o funzioni, con TeX è possibile costruire delle macro. Nel tempo sono stati realizzati diversi pacchetti standard di macro per TeX; per esempio LaTeX e AmS-TeX. Semplificando le cose, una distribuzione TeX è un insieme composto da un compilatore TeX (ma forse è più appropriato il termine «compositore»), una serie di file contenenti le informazioni necessarie a produrre i caratteri da stampa e alcuni pacchetti di macro (di solito si tratta almeno di LaTeX). La distribuzione più importante nei sistemi Unix di TeX è teTeX, questo capitolo. 1 a cui si fa riferimento in Purtroppo, una distribuzione TeX è qualcosa di estremamente complesso, dove si raccolgono apporti di autori differenti che a volte hanno scelto licenze particolari. In questo senso, la scelta di una distribuzione TeX rispetto a un’altra può significare che questa possa essere complessivamente libera o meno. Tuttavia, dal punto di vista dell’utente, è come la differenza che c’è tra un compilatore libero di un certo linguaggio e un altro compilatore non libero per lo stesso linguaggio di programmazione. In generale, l’utilizzatore di una distribuzione TeX «libera» non subisce alcun inconveniente dalle particolarità che possono avere le licenze di questo o quel componente. Il problema, semmai, si incontra nel momento in cui si voglia partecipare al suo sviluppo, a causa dell’incompatibilità che ci può essere tra licenze differenti. A questo proposito, si può osservare che molti file sono espressamente di dominio pubblico, per non creare difficoltà di alcun genere all’utilizzo in questa o quella distribuzione. Questo capitolo si colloca prima di quelli che mostrano l’uso del linguaggio TeX e alcuni concetti potrebbero sembrare oscuri. Tuttavia, è importante comprendere inizialmente, almeno a grandi linee, la struttura e il funzionamento di una distribuzione TeX. 229.1 Collocazione È importante chiarire che non esiste un modo standard di installare una distribuzione TeX e le differenze esistono anche nell’ambito della stessa distribuzione teTeX, dato che ogni distribuzione GNU/Linux tende a collocarla dove ritiene più opportuno. Il blocco principale di teTeX dovrebbe trovarsi in una gerarchia che può inserirsi al di sotto di ‘/usr/lib/’ o ‘/usr/share/’. A titolo di esempio, viene mostrato un elenco di alcune di queste possibilità. ‘/usr/lib/teTeX/texmf/’ ‘/usr/lib/texmf/texmf/’ ‘/usr/share/teTeX/texmf/’ ‘/usr/share/texmf/’ Negli esempi che si mostreranno, quando si farà riferimento a questa directory, si indicheranno solo percorsi relativi a iniziare da ‘texmf/’. La sigla «texmf» sta per TeX and more, oppure per TeX and friends. 1 teTeX GNU GPL 2453 2454 teTeX: la distribuzione Unix di TeX 229.2 Configurazione Di fronte alla complicazione di una distribuzione teTeX, potrebbe sembrare assurda l’idea di metterci le mani, pensando addirittura di modificare le impostazioni generali di teTeX. Tuttavia, quando si maneggiano documenti eccezionalmente voluminosi, potrebbe essere necessario modificare anche ciò che non è stato pensato per esserlo. 229.2.1 Modifiche manuali Alla fine della composizione di un documento TeX, si può leggere nel file delle registrazioni generato un rapporto delle risorse utilizzate durante l’elaborazione. Si osservi l’esempio. Here is how much of TeX’s memory you used: 2418 strings out of 25906 45132 string characters out of 446921 109255 words of memory out of 263001 5196 multiletter control sequences out of 10000+0 106774 words of font info for 69 fonts, out of 200000 for 1000 15 hyphenation exceptions out of 1000 33i,12n,21p,2494b,1259s stack positions out of 300i,100n,500p,30000b,4000s Output written on texput.dvi (1844 pages, 7563800 bytes). Questo è proprio il caso di un documento enorme (1844 pagine), ma prima di tale informazione appaiono una serie di valori, dove alternativamente si vede quanto di una data risorsa è stato usato e quanto era invece disponibile. Se per qualche ragione si esaurisce una di queste risorse, l’elaborazione si interrompe con una segnalazione di errore che indica quale limite è stato superato. Se succede, si può provare a mettere mano al file di configurazione di teTeX che dovrebbe essere ‘texmf/web2c/texmf.cnf’. La prima volta, non è tanto facile capire il senso delle direttive che questo contiene, ma con un po’ di tentativi si dovrebbe riuscire a risolvere il problema. Prima di tutto si può osservare che, seguendo lo stile generale di TeX, i commenti sono introdotti dal simbolo di percentuale (‘%’). Nella prima parte del file sono annotati i percorsi dei vari componenti della distribuzione. % Part 1: Search paths and directories. % The main tree, which must be mentioned in $TEXMF, below: TEXMFMAIN = /usr/share/texmf % A place for local additions to a "standard" texmf tree. % TEXMFLOCAL = /usr/share/texmf.local For example: % A place where texconfig stores modifications (instead of the TEXMFMAIN % tree). texconfig relies on the name, so don’t change it. % TEXMF_CNF = $TEXMF.cnf % User texmf trees can be catered for like this... % HOMETEXMF = $HOME/texmf La lettura di questa parte può rivelare delle informazioni importanti riguardo la propria distribuzione teTeX. Più avanti inizia una parte più delicata: quella che definisce le dimensioni degli array utilizzati da TeX, che di conseguenza rappresentano i limiti a cui si accennava all’inizio di questa sezione. teTeX: la distribuzione Unix di TeX 2455 % Part 3: Array and other sizes for TeX (and Metafont and MetaPost). ... % Max number of characters in all strings, including all error messages, % help texts, font names, control sequences. These values apply to TeX and MP. pool_size.context = 500000 pool_size.cont-en = 500000 pool_size.cont-nl = 500000 pool_size.cont-de = 500000 %pool_size = 125000 pool_size = 500000 In questa parte, il valore più importante è quello di ‘pool_size’, perché può creare problemi soprattutto a pdfTeX. Nell’esempio si vede che è stato quadruplicato. Alcune modifiche non possono essere prese in considerazione senza un’elaborazione successiva del file. In generale, al termine delle modifiche è bene dare il comando seguente: # texconfig init A parte il caso particolare dell’utilizzo appena mostrato, ‘texconfig’ è un programma interattivo, che viene descritto nella prossima sezione. 229.2.2 # texconfig ‘texconfig’ è un programma, in forma di script predisposto per configurare gli elementi essen- ziali della distribuzione teTeX. Si avvia semplicemente, senza bisogno di argomenti. La figura 229.1 mostra il menù principale di ‘texconfig’. # texconfig Figura 229.1. Il menù principale di ‘texconfig’. .---------------------------- teTeX setup utility -----------------------------. | | | Hint: all output of external commands (e.g. tex) is logged into | | a file. You can look at this file using LOG. If cursor keys make | | trouble, you may have more luck with +/- and TAB. | | | | | | .--------------------------------------------------------------------------. | | | EXIT exit | | | | PREF personal preferences | | | | CONF show configuration | | | | REHASH rebuild ls-R database | | | | HYPHEN hyphenation table (tex/latex) | | | | MODE default mode (xdvi/dvips/mf) | | | | XDVI xdvi configuration | | | | DVIPS dvips configuration | | | | FONT directories for font creation | | | | DOC rebuild html documentation | | | | FAQ frequently asked questions + answers | | | | LOG view logfile | | |------------------------------------------------------------------------------| | < OK > <Cancel> | ‘------------------------------------------------------------------------------‘ La funzione indicata con la sigla PREF serve solo a modificare il comportamento di ‘texconfig’, permettendo in particolare di selezionare un programma per la modifica del testo alternativo a quello predefinito. La funzione CONF permette di mostrare la configurazione, consistente nella definizione delle directory contenenti i vari componenti della distribuzione teTeX. teTeX: la distribuzione Unix di TeX 2456 La funzione REHASH permette di ricostruire il file ‘texmf/ls-R’, utilizzato per agevolare la ricerca dei componenti installati ad alcuni programmi della distribuzione. In generale, si ricostruisce questo file quando si aggiunte o si toglie qualche file (per esempio i file dei tipi di carattere). La funzione HYPHEN è molto importante, perché permette di stabilire le lingue per cui attivare la suddivisione in sillabe del testo. Selezionando questa funzione si ottiene l’avvio del programma per la modifica di file di testo (presumibilmente VI) con il file ‘texmf/tex/generic/config/ language.dat’. Questo file può essere modificato, quindi, dopo averlo salvato, vengono avviate automaticamente le procedure necessarie ad attivare in pratica le scelte fatte. Di solito, si tratta di commentare le righe che fanno riferimento a linguaggi che non si vogliono gestire e di togliere il commento dalla direttiva di attivazione della sillabazione per la lingua italiana. % File : language.dat % Purpose : specify which hypenation patterns to load % while running iniTeX %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % CAUTION: the first language will be the default if no style-file % (e.g. german.sty) is used. % Since version 3.0 of TeX, hyphenation patterns for multiple languages are % possible. Unless you know what you are doing, please let the american % english patterns be the first ones. The babel system allows you to % easily change the active language for your texts. For more information, % have a look to the documentation in texmf/doc/generic/babel. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % The hyphenation pattern files are in the directory: % texmf/tex/generic/hyphen % The US-english patterns should be loaded *always* and as *first* ones. american ushyph1.tex % % Let us define USenglish as an alias for american: =USenglish % % UK english, TWO LINES! %british ukhyph.tex % %=UKenglish % % english should always be defined. Either an alias for american or british. =english % % French, TWO lines! french frhyph.tex frhyphex.tex % =patois % german ghyph31.tex % % The following %bahasa %catalan %croatian %czech %danish %dutch %finnish %galician italian %magyar %norsk languages are disabled by default. Uncomment, what you need. inhyph.tex % cahyph.tex % hrhyph.tex % czhyph2e.tex % dkhyphen.tex % nehyph2.tex % fihyph.tex % gahyph.tex % ithyph.tex % huhyph.tex % nohyph.tex % teTeX: la distribuzione Unix di TeX %polish %portuges %romanian %russian %serbocroatian %slovene %spanish %swedish %turkish 2457 plhyph.tex % pthyph.tex % rohyphen.tex % ruhyph.tex % shhyphl.tex % sihyph22.tex % sphyph.tex % sehyph.tex % trhyph.tex % % A "language" without hyphenation: nohyphenation zerohyph.tex % Al termine dell’elaborazione si potrà verificare nel file ‘texmf/web2c/latex.log’ la presenza delle righe che dimostrano l’abilitazione della sillabazione per le lingue selezionate nel file di configurazione. In questo caso particolare, la lingua italiana corrisponde al linguaggio numero tre. ... \l@american=\language0 ... \l@USenglish =\language0 \l@english =\language0 \l@french=\language1 ... \l@patois =\language1 \l@german=\language2 ... \l@italian=\language3 ... \l@nohyphenation=\language4 La funzione MODE permette di predisporre alcuni programmi per la risoluzione della propria stampante. Ciò si ottiene semplicemente selezionando il nome di una stampante che dovrebbe corrispondere, o essere molto simile alla propria. La funzione XDVI permette di configurare Xdvi (capitolo 91), il programma di visualizzazione dei file DVI, in modo da stabilire il formato del foglio che si utilizza. Basta scorrere un elenco e confermare. La funzione DVIPS permette di configurare Dvips (capitolo 91), il programma in grado di convertire file DVI in PostScript. Come per Xdvi, la cosa più importante da stabilire è il formato della carta, ma può anche essere indicata la stampante, o il comando di stampa da utilizzare quando Dvips viene usato per inviare direttamente un file alla stampa. L’ultima funzione importante è FONT che permette di regolare i permessi di accesso alle directory che contengono i tipi di carattere e anche di configurare altre caratteristiche di questi file. 229.3 Funzionamento fondamentale di TeX TeX utilizza un sorgente che si distingue perché di solito il suo nome finisce con l’estensione ‘.tex’; durante il processo di composizione genera un rapporto sull’elaborazione in un file con l’estensione ‘.log’ e produce un file finale in formato DVI, con estensione ‘.dvi’. Successivamente, i file DVI vengono convertiti normalmente in PostScript attraverso il programma Dvips. Eventualmente, è disponibile anche pdfTeX, con cui, invece di una composizione in formato DVI, si ottiene un file PDF senza passaggi intermedi. teTeX: la distribuzione Unix di TeX 2458 Se si suppone che il file ‘primo.tex’ contenga il testo seguente Ciao a tutti. Questo \‘e il mio primo documento scritto con il linguaggio \TeX. \bye per ottenere la composizione in formato DVI è sufficiente il comando $ tex primo.tex[ Invio ] This is TeX, Version 3.14159 (Web2C 7.3.1) (primo.tex [1] ) Output written on primo.dvi (1 page, 328 bytes). Transcript written on primo.log. mentre per ottenere la composizione in formato PDF è sufficiente il comando $ pdftex primo.tex[ Invio ] This is pdfTeX, Version 3.14159-13d (Web2C 7.3.1) (primo.tex[/usr/share/texmf/pdftex/config/pdftex.cfg] Babel <v3.6x> and hyphenation patterns for american, italian, nohyphenation, loaded. [1[/usr/share/texmf/dvips/config/pdftex.map]] )<cmr10.pfb> Output written on primo.pdf (1 page, 9807 bytes). Transcript written on primo.log. Nel primo caso si ottiene il file ‘primo.dvi’, mentre nel secondo si ha il file ‘primo.pdf’. Eventualmente, per convertire il file DVI in PostScript, è sufficiente usare Dvips nel modo seguente: $ dvips -o primo.ps primo.dvi[ Invio ] This is dvips(k) 5.86 Copyright 1999 Radical Eye Software (www.radicaleye.com) ’ TeX output 2001.08.30:0835’ -> primo.ps <texc.pro>. [1] Ecco quello che si ottiene: Si può anche usare una versione estesa di TeX, e-TeX e pdfeTeX, corrispondenti agli eseguibili ‘etex’ e ‘pdfetex’, che in questo caso si comportano nello stesso modo: $ etex primo.tex[ Invio ] This is e-TeX, Version 3.14159-2.1 (Web2C 7.3.1) entering extended mode (primo.tex [1] ) Output written on primo.dvi (1 page, 328 bytes). Transcript written on primo.log. oppure $ pdfetex primo.tex[ Invio ] This is pdfeTeX, Version 3.14159-13d-2.1 (Web2C 7.3.1) entering extended mode (primo.tex[/usr/share/texmf/pdftex/config/pdftex.cfg] [1[/usr/share/texmf/dvips /config/pdftex.map]] )<cmr10.pfb> Output written on primo.pdf (1 page, 9807 bytes). Transcript written on primo.log. teTeX: la distribuzione Unix di TeX 2459 Gli eseguibili ‘tex’, ‘pdftex’ ‘etex’ e ‘pdfetex’ sono indipendenti, mentre attorno a loro si presentano altrettante serie di collegamenti simbolici: virtex initex latex amstex -> -> -> -> tex tex tex tex evirtex einitex elatex -> etex -> etex -> etex pdfevirtex -> pdfetex pdfeinitex -> pdfetex pdfelatex -> pdfetex pdfvirtex pdfinitex pdflatex -> pdftex -> pdftex -> pdftex A seconda del nome usato per avviare uno stesso eseguibile, si può ottenere un comportamento differente. Nel caso di ‘virtex’ che è un collegamento a ‘tex’, si fa riferimento implicitamente al formato ‘plain’, corrispondente alle dichiarazioni contenute nei file della directory ‘texmf/tex/plain/’, così come ‘pdfvirtex’ fa riferimento alla directory ‘texmf/pdftex/ plain/’, ecc. Purtroppo, le cose non sono così semplici in generale, perché le convenzioni non sono perfettamente omogenee; tuttavia, vale la pena di tenere presente che i nomi del tipo ‘[pdf][e]virtex’ sono equivalenti ai nomi del tipo ‘[pdf][e]tex’. I nomi del tipo ‘[pdf][e]initex’ fanno riferimento al linguaggio TeX senza la dichiarazione di alcuna macro e sono equivalenti all’uso degli eseguibili del tipo ‘[pdf][e]tex’ con l’aggiunta dell’opzione ‘--ini’. In pratica, per usare ‘[pdf][e]initex’, oppure ‘[pdf][e]tex --ini’, occorre modificare l’esempio già visto nel modo seguente: \input plain Ciao a tutti. Questo \‘e il mio primo documento scritto con il linguaggio \TeX. \bye Questa spiegazione viene data solo per chiarire un po’ il funzionamento di TeX e il significato di tutti i collegamenti simbolici che gli stanno intorno. L’uso dell’istruzione ‘\input plain’ nel sorgente non funziona sempre come ci si aspetterebbe leggendo queste indicazioni; in pratica, una volta capito il senso della cosa, non va usata affatto. In modo analogo a quanto visto fino a questo punto, quando si fa riferimento a un collegamento del tipo ‘[pdf][e]latex’, è come usare un eseguibile del tipo ‘[pdf][e]initex’, oppure ‘[pdf][e]tex --ini’, iniziando il sorgente TeX con la riga seguente: \input latex.ini Resta il fatto che il comando ‘\input latex.ini’ non rappresenta necessariamente uno standard e quello che conta è sapere solo che i collegamenti ‘[pdf][e]latex’ richiamano in qualche modo il formato ‘latex’. In altri termini, i collegamenti ‘[pdf][e]latex’ fanno riferimento implicitamente alle macro di LaTeX. Per completare questa sezione, viene mostrato un esempio di un sorgente LaTeX, ovvero un sorgente TeX fatto per le macro LaTeX. Si fa riferimento al nome ipotetico ‘secondo.tex’: teTeX: la distribuzione Unix di TeX 2460 \documentclass{article} \begin{document} Ciao a tutti. Questo \‘e il mio primo documento scritto con il linguaggio \LaTeX . \end{document} Per comporre correttamente questo file, occorre un comando del tipo: $ [pdf][e]latex secondo.tex A seconda dei casi si otterrà il file ‘secondo.dvi’, oppure ‘secondo.pdf’. 229.4 Interazione con TeX La composizione di un documento scritto con il linguaggio TeX può avvenire anche con qualche forma di interazione. Se si avvia uno degli eseguibili ‘[pdf][e]tex’ senza argomenti, si ottiene un invito a inserire il nome del file, attraverso l’indicazione di due asterischi: $ tex[ Invio ] This is TeX, Version 3.14159 (Web2C 7.3.1) ** Si può inserire così il percorso del file, omettendo eventualmente l’estensione se questa corrisponde a ‘.tex’: **terzo.tex[ Invio ] (terzo.tex [1] ) Output written on terzo.dvi (1 page, 488 bytes). Transcript written on terzo.log. Supponendo di avere scritto un file, denominato ‘quarto.tex’, in cui non appare l’istruzione ‘\bye’ finale, come nel testo seguente, TeX si ferma in attesa di istruzioni, mostrando un invito ridotto a un solo asterisco: Ciao a tutti. Questo \‘e il mio quarto documento scritto con il linguaggio \TeX, dove non appare l’istruzione $\backslash$bye alla fine del file. $ tex quarto.tex[ Invio ] This is TeX, Version 3.14159 (Web2C 7.3.1) (quarto.tex) * Naturalmente, se si è in grado di farlo, si può aggiungere anche altro testo: *Saluti![ Invio ] *\bye[ Invio ] [1] Output written on quarto.dvi (1 page, 448 bytes). Transcript written on quarto.log. !"#$ % && ' ( ) * + , -, . / teTeX: la distribuzione Unix di TeX 2461 Di solito si evita di interagire con TeX, tuttavia si può essere costretti dal presentarsi di un errore durante la compilazione del sorgente. Per la precisione, il livello di interazione di TeX può essere regolato attraverso delle istruzioni speciali, come descritto nella tabella 229.1. In condizioni normali, il funzionamento avviene in modalità ‘errorstopmode’, corrispondente all’istruzione ‘\errorstopmode’, in cui TeX si ferma in attesa di indicazioni per qualunque errore si presenti. Tabella 229.1. Istruzioni per il controllo della modalità di funzionamento interattiva. Istruzione TeX \errorstopmode \scrollmode \nonstopmode \batchmode Modalità di funzionamento La composizione viene sospesa per qualunque errore. La composizione viene sospesa solo per gli errori più importanti. La composizione viene sospesa solo in presenza di errori gravissimi. La composizione viene sospesa solo in presenza di errori gravissimi e non si mostrano informazioni sullo schermo. Per esempio, il file ‘quinto.tex’ che contiene il testo seguente, usa erroneamente l’istruzione ‘\tex’ al posto di ‘\TeX’: Ciao a tutti. Questo \‘e il mio quinto documento scritto con il linguaggio \tex, in cui si provoca volutamente un errore. \bye $ tex quinto.tex[ Invio ] This is TeX, Version 3.14159 (Web2C 7.3.1) (quinto.tex ! Undefined control sequence. l.3 ...to documento scritto con il linguaggio \tex , in ? Viene dichiarato sinteticamente il tipo di errore individuato, che in questo caso corrisponde a ! Undefined control sequence. ovvero una sequenza di controllo indefinita. Nella riga successiva si indica il numero della riga in cui appare l’errore (‘l.3’ sta per line 3) con il pezzo di testo che arriva fino all’errore, mentre il pezzo successivo appare staccato, nella riga successiva. l.3 ...to documento scritto con il linguaggio \tex , in In pratica, secondo TeX l’errore è riferito esattamente alla stringa ‘\tex’. Sotto appare un invito composto da un punto interrogativo, con il quale TeX attende un’azione dell’utente. Si può rispondere con un altro punto interrogativo per avere l’elenco delle possibilità: ??[ Invio ] Type <return> to proceed, S to scroll future error messages, R to run without stopping, Q to run quietly, I to insert something, E to edit your file, 1 or ... or 9 to ignore the next 1 to 9 tokens of input, H for help, X to quit. ? La tabella 229.2 descrive brevemente il significato e l’uso dei comandi disponibili, mostrando anche la modalità corrispondente quando una scelta coincide con la richiesta di cambiamento di questa. teTeX: la distribuzione Unix di TeX 2462 Tabella 229.2. Interazione in presenza di un errore. Istruzione TeX corrispondente Effetto [ r ][ Invio ] \scrollmode \nonstopmode [ q ][ Invio ] \batchmode Mostra la spiegazione del motivo dell’interruzione. Richiede di inserire una correzione. Avvia un programma per la modifica del file sorgente. Arresta la composizione. Non si ferma più in presenza di piccoli errori. Non si ferma più per alcun errore. Non si ferma più per alcun errore e non mostra alcuna informazione. Cerca di rimediare all’errore e continua la composizione. Cerca di rimediare automaticamente ai prossimi n errori. Tastiera [ h ][ Invio ] [ i ][ Invio ] [ e ][ Invio ] [ x ][ Invio ] [ s ][ Invio ] [ Invio ] [ n ][ Invio ] Nel caso dell’errore mostrato, si vuole provare a capire meglio di cosa si tratta, attraverso il comando [ h ][ Invio ]: ?h[ Invio ] The control sequence at the end of the top line of your error message was never \def’ed. If you have misspelled it (e.g., ‘\hobx’), type ‘I’ and the correct spelling (e.g., ‘I\hbox’). Otherwise just continue, and I’ll forget about whatever was undefined. Dal momento che si può correggere facilmente l’errore, si richiede di poter inserire del testo sostitutivo: ?i[ Invio ] insert>\TeX[ Invio ] [1] ) Output written on quinto.dvi (1 page, 376 bytes). Transcript written on quinto.log. Con il comando [ e ][ Invio ] si può avviare un programma per la modifica del file sorgente. Di solito si tratta di VI, ma si può intervenire nella variabile di ambiente ‘TEXEDIT’ indicando il nome di un altro programma, usando le metavariabili ‘%d’ e ‘%s’ per indicare rispettivamente la riga contenente l’errore e il nome del file. Per esempio, rimanendo nel caso di VI, è possibile usare la sintassi seguente per raggiungere la riga n -esima del file indicato: vi -c n file In questo modo, si dovrebbe assegnare alla variabile di ambiente ‘TEXEDIT’ la stringa ‘vi -c %d %s’: $ TEXEDIT="vi -c %d %s"[ Invio ] $ export TEXEDIT[ Invio ] teTeX: la distribuzione Unix di TeX 229.5 Riferimenti • Documentazione interna della distribuzione teTeX: ‘texmf/doc/*’ • Documentazione interna Info: web2c.info e latex.info Appunti di informatica libera 2003.01.01 --- Copyright © 2000-2003 Daniele Giacomini -- daniele @ swlibero.org 2463 Capitolo 230 TeX: introduzione TeX è un linguaggio di programmazione per la composizione tipografica. La «compilazione» di un sorgente TeX produce un file in formato finale (DVI o PDF) per la stampa. L’importanza di questo linguaggio richiede anche la conoscenza della pronuncia corretta del suo nome: «t-e-k». Infatti, il creatore di questo linguaggio, D.E. Knuth, voleva fare riferimento alle lettere greche maiuscole «TEX», che così vanno pronunciate. Dal momento che le istruzioni TeX utilizzano spesso le parentesi graffe, nei modelli sintattici queste vanno intese letteralmente, come parte dell’istruzione rappresentata. 230.1 Elementi essenziali del linguaggio TeX Un file sorgente TeX è un file di testo normale; per la precisione dovrebbe trattarsi di un file ASCII standard a 7 bit, dove l’interruzione delle righe avviene secondo le regole del proprio sistema operativo. Nel linguaggio di TeX si distinguono righe bianche o vuote da righe contenenti istruzioni. Nell’ambito delle righe contenenti istruzioni, possono poi apparire dei commenti che si distinguono per essere preceduti dal segno di percentuale (‘%’), terminati dalla fine della riga. Nell’esempio seguente si può osservare che tutte le righe che contengono del testo sono in pratica delle istruzioni, più o meno articolate. Nella prima riga appare anche un commento, che non appare poi nella composizione finale. Ciao a tutti. % Ecco, un commento tanto per gradire. Questo \‘e solo un piccolo esempio per vedere come funziona il linguaggio di composizione \TeX. \bye Gli spazi, verticali e orizzontali, hanno un significato, ma generalmente non si sommano. Normalmente si usa una riga vuota o bianca per separare il testo in paragrafi, ma la presenza di più righe bianche o vuote non cambia la distanza tra questi paragrafi nella composizione finale; nello stesso modo, uno spazio orizzontale serve generalmente a separare le parole di una frase, ma la presenza di più spazi orizzontali non cambia la distanza tra le parole. Eventualmente si può dichiarare espressamente la separazione tra i paragrafi attraverso l’istruzione ‘\par’, tenendo presente che anche in questo caso, l’uso di più istruzioni del genere non produce una separazione maggiore tra i paragrafi stessi L’istruzione finale ‘\bye’ conclude il «programma» TeX e tutto ciò che appare dopo viene ignorato. 230.1.1 Testo letterale, parole e simboli di controllo Una riga di testo si traduce generalmente nel testo corrispondente nella composizione finale, tenendo conto però che alcuni simboli hanno un significato speciale e si distinguono contesti differenti. La tabella 230.1 elenca i caratteri che hanno significati particolari, con l’indicazione del modo per ottenere il loro simbolo originale nella composizione. 2464 TeX: introduzione 2465 Tabella 230.1. Elenco dei caratteri che hanno significati particolari. Carattere speciale \ { } % & ~ $ ^ _ # <SP> < > Utilizzo normale Prefisso di una parola di controllo o di un simbolo di controllo. Apre un gruppo. Chiude un gruppo. Inizia un commento fino alla fine della riga. Tabulazione orizzontale. Spazio non interrompibile. Inizia e conclude un contesto matematico. Apice, in un contesto matematico. Pedice, in un contesto matematico. Definisce la collocazione di un parametro. Uno o più spazi vengono ridotti a uno solo. In condizioni normali, genera un punto esclamativo rovesciato. In condizioni normali, genera un punto interrogativo rovesciato. Trasformazione per l’uso letterale $\backslash$ $\{$ $\}$ \% \& \~{} \$ \^{} \_{} \# \<SP> $<$ $>$ La barra obliqua inversa (‘\’) viene usata come prefisso per delle sequenze di controllo , nell’ambito delle quali si può distinguere tra parole di controllo e simboli di controllo . Una parola di controllo è formata esclusivamente da lettere alfabetiche (dalla «a» alla «z», maiuscole e minuscole, escluse le lettere accentate); per esempio, ‘\TeX’ è una parola di controllo con cui si ottiene la rappresentazione del nome TeX secondo lo standard stabilito dal suo autore originale. Un simbolo di controllo è invece un solo carattere che non sia una lettera alfabetica; per esempio, ‘\‘’ è un simbolo di controllo con cui si ottiene l’aggiunta di un accento grave sopra il simbolo successivo. In base al fatto che le parole di controllo si distinguono perché composte esclusivamente da lettere alfabetiche, si può porre il problema di delimitarle correttamente quando si trovano incorporate in parole che compongono il testo normale. Nell’esempio già mostrato, la parola di controllo ‘\TeX’ si individua correttamente perché è seguita da un punto fermo, ovvero un simbolo che non è una lettera alfabetica, ma volendo scrivere un gioco di parole, come «il mio primo TeXdocumento», sarebbe necessario usare uno strattagemma. Si osservi l’esempio seguente che si traduce in un errore nella composizione del documento: Ciao a tutti. Questo \‘e il mio primo \TeXdocumento. \bye TeX cerca di interpretare la parola di controllo ‘\TeXdocumento’ e non dovrebbe riuscirci. Per questa ragione, lo spazio che dovesse seguire una parola di controllo viene ignorato; così, diventa più facile inserire queste parole di controllo in parole del testo che si vuole comporre. Ecco l’esempio corretto: Ciao a tutti. Questo \‘e il mio primo \TeX documento. \bye Tuttavia, rimane da chiarire in che modo inserire veramente uno spazio dopo una parola di controllo. Questo problema viene risolto con l’uso dei raggruppamenti. TeX: introduzione 2466 230.1.2 Raggruppamenti In diverse situazioni è utile raggruppare parte delle istruzioni (il testo) all’interno di parentesi graffe (‘{...}’). L’effetto del raggruppamento non si nota nella composizione finale, ma permette di circoscrivere l’effetto di istruzioni particolari. È ammissibile anche l’uso di raggruppamenti vuoti, ‘{}’, che di solito vengono usati per separare parole o simboli di controllo dal testo che segue. Per esempio, scrivendo ‘\TeX{}’ si riesce a evitare che lo spazio successivo venga inghiottito.1 Nel seguito vengono mostrati diversi esempi che si traducono nella stessa composizione finale. • Raggruppamento vuoto alla fine della parola di controllo: Il linguaggio di composizione \TeX{} sembra complesso a prima vista... \bye • Raggruppamento vuoto per separare gli spazi: Il linguaggio di composizione \TeX {} sembra complesso a prima vista... \bye • Raggruppamento per individuare uno spazio: Il linguaggio di composizione \TeX{ }sembra complesso a prima vista... \bye • Raggruppamento per individuare uno spazio dopo la fine della parola di controllo: Il linguaggio di composizione \TeX { }sembra complesso a prima vista... \bye • Raggruppamento per isolare la parola di controllo: Il linguaggio di composizione {\TeX} sembra complesso a prima vista... \bye • Raggruppamento per isolare lo spazio e la parola successiva: Il linguaggio di composizione \TeX { sembra} complesso a prima vista... \bye Nella tabella 230.1 sono stati mostrati alcuni simboli di controllo che sono conclusi evidentemente da un raggruppamento vuoto: ‘\~{}’, ‘\^{}’ e ‘\_{}’. In questo caso, il raggruppamento vuoto serve a impedire che la sequenza di controllo produca qualcosa di diverso da ciò che ci si aspetta in quel contesto particolare. Per esempio, ‘\^o’ oppure anche ‘\^ o’ genera la lettera accentata «ô».2 Oltre all’uso delle parentesi, è possibile usare in alternativa la coppia di parole di controllo ‘\bgroup’ e ‘\egroup’, in sostituzione di ‘{’ e ‘}’ rispettivamente. 230.1.3 Inclusione di file esterni È possibile articolare un sorgente TeX in più file separati, che vengono inclusi con l’istruzione ‘\input’: \input nome_file 1 Naturalmente si può usare anche il simbolo di controllo ‘\<SP>’ (barra obliqua inversa e spazio) per indicare espressamente uno spazio in quel punto. 2 Verrà chiarito in seguito che le istruzioni ‘\~{}’ e ‘\^{}’ sono delle macroistruzioni che servono a generare un accento, utilizzano un parametro, costituito dal carattere o dal gruppo successivo. Nel momento in cui si vogliono rappresentare questi simboli senza abbinarli ad altro, il loro parametro deve essere un gruppo vuoto o lo spazio inteso come carattere (‘\<SP>’). Pertanto, in alternativa a ‘\~{}’ e ‘\^{}’ si poteva usare la forma ‘\~\<SP>’ e ‘\^\<SP>’. TeX: introduzione 2467 L’inclusione avviene inserendo in quel punto le righe del file indicato. Se il file esterno contiene l’istruzione ‘\bye’, la composizione termina senza continuare nel file di partenza. 2468 TeX: introduzione 230.2 Variabili e tipi di dati TeX ha una gestione molto particolare dei dati. Nelle sezioni seguenti vengono descritti solo i tipi di dati più comuni, ma questo dovrebbe bastare per far comprendere la logica di fondo. Vale la regola per cui può essere usato solo ciò che è già stato dichiarato; inoltre, il campo di azione di queste variabili può essere controllato attraverso i raggruppamenti con le parentesi graffe. In generale, per TeX una variabile ha l’aspetto di una parola di controllo a cui si assegna un valore secondo la sintassi seguente: \nome =valore L’espansione di una variabile avviene inserendo la parola di controllo corrispondente nel punto in cui il contesto lo richiede. Tuttavia, se lo scopo è quello di espandere la variabile in modo che appaia nel testo normale, occorre usare un accorgimento, con cui si trasforma il suo contenuto in una stringa. Di solito si usa per questo la parola di controllo ‘\the’: \the\nome 230.2.1 Stringhe Per TeX la stringa è ciò che può essere reso tipograficamente; così, un’espressione stringa è ciò che alla fine si trasforma in una stringa nella composizione tipografica. Le variabili di tipo stringa si dichiarano nel modo seguente: \newtoks\nome Si può assegnare una stringa alla variabile nel modo seguente: \nome ={espressione_stringa } L’espansione di una variabile stringa non può avvenire inserendo semplicemente la parola di controllo ‘\nome ’ nel testo, perché occorre dichiarare espressamente questa intenzione con la parola di controllo ‘\the’. \newtoks\data \data={9 settembre 2001} Treviso, \the\data \par Bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla. \par Ciao. Nell’esempio precedente, si crea una variabile stringa corrispondente alla parola di controllo ‘\data’, a cui si assegna la stringa ‘9 settembre 2001’, per poi ottenerne successivamente l’espansione nel testo. TeX: introduzione 2469 230.2.2 Trasformazione delle stringhe Le trasformazioni più comuni sulle stringhe sono il cambiamento in maiuscole o minuscole. Ciò si ottiene facilmente con le macro ‘\uppercase’ e ‘\lowercase’: \uppercase{espressione_stringa_da_trasformare_in_maiuscole } \lowercase{espressione_stringa_da_trasformare_in_minuscole } 230.2.3 Contatori La variabile numerica più semplice di TeX è il contatore. Ne esistono due tipi: uno deve essere inizializzato subito, con un valore non negativo, l’altro no: \countdef\nome_contatore =n \newcount\nome_contatore Il primo di questi due modelli riguarda il tipo di contatore che deve essere inizializzato in fase di dichiarazione. Il valore di inizializzazione è rappresentato da n . Per assegnare un valore a una variabile contatore, si usa la forma seguente: \nome =valore È importante sottolineare che l’inizializzazione di un contatore definito attraverso ‘\countdef’ potrebbe in pratica non tradursi nell’assegnamento corrispondente alla variabile, pur essendo obbligatorio. Pertanto, conviene poi assegnare nuovamente il valore richiesto. Si può assegnare un numero espresso usando cifre numeriche, con un segno anteriormente nel caso sia necessario, senza separatore decimale, come nell’esempio seguente, in cui si assegna al contatore ‘\conteggio’ il valore -345. \conteggio=-345 230.2.4 Lunghezze Un tipo specifico di variabile numerica è adibita a contenere delle lunghezze. Per TeX, la lunghezza è un’informazione numerica particolare, che si potrebbe ricondurre al concetto di variabile a virgola mobile di altri linguaggi. Si dichiara una lunghezza nel modo seguente: \newdimen\nome_lunghezza Una lunghezza è un valore che si può rappresentare in forma costante solo specificando l’unità di misura, che per TeX è una sigla composta da due lettere secondo lo schema che appare nella tabella 230.2. Pertanto, un valore che esprime una lunghezza deve avere la forma seguente: [+|-]numero [true]unità_di_misura In particolare, il valore che precede l’unità di misura può contenere una virgola decimale, espressa attraverso il punto (‘.’).3 Per esempio, per esprimere una lunghezza di 10 cm, si deve scrivere ‘10cm’.4 Nell’esempio seguente si assegna alla variabile ‘\distanza’ una lunghezza positiva di 4,5 mm: 3 È consentito anche l’uso della virgola per separare la parte intera di un numero. Tuttavia, ci sono situazioni in cui ciò non va bene, per cui è meglio usare sempre solo il punto. 4 TeX ammette che tra il numero e l’unità di misura ci sia dello spazio. Qui si preferisce attaccare l’unità di misura al numero, per evitare confusione con il testo successivo. TeX: introduzione 2470 \distanza=4.5mm La parola chiave ‘true’ consente di indicare una lunghezza che non può essere ingrandita o ridotta attraverso l’istruzione ‘\magnification’, come verrà descritto nella sezione 232.1. Pertanto, se nell’esempio precedente si vuole indicare una lunghezza positiva corrispondente esattamente a 4,5 mm, in ogni situazione, si deve scrivere così: \distanza=4.5truemm oppure anche in modo più leggibile: \distanza=4.5 true mm La rappresentazione interna delle lunghezze è di un solo tipo; in pratica, TeX converte sempre i valori nell’unità di misura più piccola che è in grado di gestire.5 Tabella 230.2. Unità di misura secondo TeX. Sigla mm cm in Denominazione millimetro centimetro pollice Corrispondenza bp big point pt punto dd punto didôt sp scaled point 1/65535 punti ‘pt’ pc pica 12 punti em M variabile ex x variabile mu math unit 18 quadratoni 2,54 cm 0,3527777 mm 1/72 pollici 0,3514598 mm 1/72,27 pollici 0,376065 mm 1/67,54 pollici Annotazioni Il punto tipografico usato dal linguaggio PostScript. Punto tipografico usato negli Stati Uniti. Punto tipografico europeo. L’unità di misura più piccola gestibile da TeX. Quadratone, pari alla larghezza della lettera «M» maiuscola. Altezza della lettera «x» minuscola. Si osservi che TeX non semplifica la tradizione tipografica, consentendo di utilizzare ben tre tipi diversi di punto tipografico. Il punto a cui si è abituati comunemente con i programmi di composizione, è quello corrispondente alla sigla ‘bp’, ma TeX utilizza in modo predefinito l’unità ‘pt’, che comunque non si discosta di molto. 230.2.5 Lunghezze elastiche In varie situazioni, TeX è in grado di gestire delle lunghezze elastiche. Le variabili che contengono informazioni del genere sono in grado di annotare tre indicazioni distinte: la distanza normale, una tolleranza in più e una tolleranza in meno. Questo tipo di informazione si esprime secondo la forma seguente: lunghezza_richiesta [plus lunghezza_in_estensione ] [minus lunghezza_in_contrazione ] In pratica, è come dire che si fa riferimento a una certa lunghezza, a cui si può aggiungere quanto appare dopo la parola chiave ‘plus’ e si può togliere quanto appare dopo ‘minus’. Come si può intuire, quando non si indicano i valori che danno elasticità, si sottintende in corrispondenza un valore zero. 5 L’unità di misura più piccola è definita scaled point, che è stata creata appositamente per TeX. TeX: introduzione 2471 L’elasticità fissata attraverso le parole chiave ‘plus’ e ‘minus’ non è tassativa. Di solito, il solo fatto che si consenta un’estensione, anche di un solo punto, fa sì che il salto sia allungabile in modo indefinito, in caso di necessità. Eventualmente, si dichiara una variabile del genere con la forma seguente: \newskip\nome L’assegnamento, come si può intendere, ha la forma seguente: \nome =lunghezza_elastica Ovvero: \nome =lunghezza [plus lunghezza ] [minus lunghezza ] Le indicazioni sull’elasticità in estensione e in contrazione sono formate normalmente da lunghezze, come per esempio ‘plus 1pt’, ma si possono usare anche delle definizioni astratte, rappresentate da tre parole chiave, precedute da un numero intero: n fil n fill n filll Generalmente, il numero n è sempre 1 e va inteso come moltiplicatore della parola successiva; in pratica, ‘2fil’ rappresenta un’elasticità doppia di ‘1fil’. La parola chiave ‘fil’ rappresenta un’elasticità di grado minimo, ‘fill’ un’elasticità di grado medio e ‘filll’ un’elasticità molto grande. 230.2.6 Operazioni con i valori numerici La realizzazione di espressioni numeriche con TeX diventa abbastanza complicata. Si utilizzano fondamentalmente tre tipi di istruzione per modificare il valore di una variabile: [by] valore \multiply\nome [by] valore \divide\nome [by] valore \advance\nome In pratica, nel primo caso si incrementa la variabile del valore indicato (se il valore in questione è negativo, la variabile viene ridotta di conseguenza); nel secondo caso di assegna alla variabile il prodotto tra quanto contenuto prima per il valore indicato; nel terzo caso si divide il contenuto della variabile per il valore, assegnando alla stessa il risultato della divisione. Come si può osservare, la parola chiave ‘by’ è facoltativa e si può usare per facilitare la lettura umana dell’istruzione. Il valore usato deve essere del tipo adatto alla variabile con cui si esegue l’operazione. Viene mostrato un esempio complessivo che dovrebbe essere comprensibile a sufficienza: TeX: introduzione 2472 \countdef\pagina=0 \pagina=1 \newcount\contatore \contatore=-7 \newdimen\lunghezza \lunghezza=100pt \newskip\elastico \elastico=10pt plus 2pt minus 1pt pagina = \the\pagina \par contatore = \the\contatore \par lunghezza = \the\lunghezza \par elastico = \the\elastico \par \multiply\pagina by 2 \advance\contatore by 1 \advance\lunghezza by 10pt \advance\elastico by 5pt plus 3pt minus 2pt pagina = \the\pagina \par contatore = \the\contatore \par lunghezza = \the\lunghezza \par elastico = \the\elastico \par \divide\lunghezza by 2 \divide\elastico by 2 lunghezza = \the\lunghezza \par elastico = \the\elastico \par ! " # # !# # # % # $ # Va tenuta in considerazione una scorciatoia importante per rappresentare il prodotto tra una costante numerica e il valore di una lunghezza, che si usa di solito per gli assegnamenti: n \nome In questo caso, il numero n non deve esprimere una lunghezza, pertanto non può contenere l’indicazione dell’unità di misura. Per esempio, se ‘\hsize’ contiene la lunghezza 15 cm, con l’istruzione seguente si assegna alla variabile ‘\mezza’ la metà di questa lunghezza, ovvero 7,5 cm: \mezza=0.5\hsize Nell’esempio seguente si creano due variabili: una contiene una lunghezza e l’altra una lunghezza elastica. Dopo aver controllato il valore iniziale di queste, si riassegna loro la metà del loro valore di partenza, controllando successivamente il risultato ottenuto. Si può osservare che ‘\elastico’ perde l’informazione sull’elasticità, diventando una lunghezza normale. \newdimen\lunghezza \lunghezza=100pt \newskip\elastico \elastico=10pt plus 2pt minus 1pt lunghezza = \the\lunghezza \par elastico = \the\elastico \par \lunghezza=0.5\lunghezza \elastico=0.5\elastico TeX: introduzione 2473 lunghezza = \the\lunghezza \par elastico = \the\elastico \par 230.2.7 Trasformazione in stringa di dati numerici I dati numerici, quando devono essere convertiti in stringhe, possono essere rappresentati in forme differenti. La parola di controllo ‘\the’ consente di ottenere una trasformazione «normale» di qualunque variabile in stringa: \the\parola_di_controllo Per esempio, se ‘\lunghezza’ è stata dichiarata come lunghezza contenente il valore 10 cm, l’espansione di ‘\the\lunghezza’ può generare la stringa ‘284.45274pt’. Un valore numerico può essere trasformato in numero intero, ammesso che ciò abbia senso, con la parola di controllo ‘\number’: \number\parola_di_controllo In questo caso, se si tenta di trasformare una lunghezza in numero, si ottiene la dimensione in punti scaled point; nel caso dell’esempio precedente, si otterrebbe la rappresentazione del valore 18646798, corrispondente ai 10 cm di prima espressi secondo l’unità di misura minima che TeX è in grado di gestire. Per quanto riguarda le lunghezze elastiche, non è possibile usare la trasformazione attraverso ‘\number’. Quando il valore da trasformare è un intero positivo maggiore di zero, si può ottenere la rappresentazione in numero romano, con lettere minuscole, attraverso la parola di controllo ‘\romannumeral’: \romannumeral\parola_di_controllo L’esempio seguente riepiloga l’uso delle forme di trasformazione dei dati numerici in stringa che sono appena state descritte: \newdimen\lunghezza \newcount\contatore \newcount\pagina \lunghezza=1cm \contatore=-7 \pagina=123 lunghezza = \the\lunghezza\ = \number\lunghezza scaled point \par contatore = \the\contatore\ = \number\contatore \par pagina = \the\pagina\ = \number\pagina = \romannumeral\pagina \par !#" #" $% $ & ' ' TeX: introduzione 2474 230.2.8 Controllo del campo di azione delle variabili Le parentesi graffe, oppure le parole di controllo ‘\bgroup’ e ‘\egroup’, servono a delimitare e isolare una zona rispetto al testo che si trova al loro esterno. Una dichiarazione o un assegnamento fatto all’interno di una zona delimitata da parentesi graffe ha effetto in quell’ambito e in tutte le altre zone che possono essere annidate al suo interno, mentre all’esterno non esiste più. Si osservi l’esempio seguente: \newdimen\lunghezza \newcount\contatore \lunghezza=1cm \contatore=7 { \lunghezza=10cm \contatore=14 { \lunghezza=100cm \contatore=21 lunghezza = \the\lunghezza{} contatore = \the\contatore \par } lunghezza = \the\lunghezza{} contatore = \the\contatore \par } lunghezza = \the\lunghezza{} contatore = \the\contatore \bye Si otterrà il testo che segue: Perché un assegnamento abbia valore in modo globale, si usa la parola di controllo ‘\global’. Si osservi l’esempio seguente: \newdimen\lunghezza \newcount\contatore \lunghezza=1cm \contatore=7 { \lunghezza=10cm \contatore=14 { \global\lunghezza=100cm \contatore=21 lunghezza = \the\lunghezza{} contatore = \the\contatore \par } lunghezza = \the\lunghezza{} contatore = \the\contatore \par } lunghezza = \the\lunghezza{} contatore = \the\contatore \bye In questo caso, la lunghezza appare essere sempre di 100 cm (2845,27559 punti normali), anche quando si ritorna al di fuori dei raggruppamenti. In pratica, si otterrà il testo che segue: TeX: introduzione 2475 230.2.9 Ordine nell’espansione delle sequenze di controllo Esiste un problema con TeX, legato all’ordine in cui vengono espanse le parole di controllo. L’esempio più comune è dato dalla difficoltà con cui si riesce a trasformare un numero romano ottenuto da ‘\romannumeral’ in maiuscolo. Per esempio, \newcount\pagina \pagina=4 \uppercase{\romannumeral\pagina} genera solo: In pratica, ‘\uppercase’ si trova a intervenire su una stringa che ancora non c’è, per cui non succede nulla. Per risolvere il problema si usa la parola di controllo ‘\expandafter’ che anticipa l’esecuzione di ciò che segue: \newcount\pagina \pagina=4 \uppercase\expandafter{\romannumeral\pagina} Purtroppo il funzionamento di questa parola di controllo non è intuitivo e spesso si devono fare vari tentativi prima di riuscire a fare ciò che si intende. 230.3 Dichiarazione di macroistruzioni Si può dare un nome a un’espressione stringa attraverso la sintassi seguente: \def\nome {espressione_stringa } Si osservi che, al contrario di altre situazioni, qui TeX richiede che la parentesi graffa aperta segua immediatamente il nome (o il simbolo dell’ultimo parametro, come verrà descritto nel seguito), senza alcuna spaziatura intermedia. Questo tipo di dichiarazione serve in generale per realizzare delle macroistruzioni; tuttavia, utilizzandola solo così, si fa in modo di ottenere l’espansione di ciò che è contenuto fra le parentesi graffe nel momento in cui si inserisce nel testo l’istruzione ‘\nome ’. Si osservi l’esempio: \def\eTeX{e-\TeX} Bla bla bla bla \eTeX{} bla bla... \bye In questo caso si vuole dichiarare la parola di controllo ‘\eTeX’, con cui diventa facile uniformare la scrittura di questo nome nel testo. Se ci fosse un ripensamento sulla forma da dare al nome, basterebbe modificare la sua dichiarazione iniziale. Una macro del genere può essere modificata solo riassegnandole un altro valore, nello stesso modo usato per la sua dichiarazione iniziale. È importante ricordare che in fase di composizione, le parole di controllo assorbono gli spazi alla loro destra, per cui è necessario usare una tecnica per evitarlo, che di solito si riduce all’inserimento di un gruppo vuoto alla fine della stessa. TeX: introduzione 2476 Nel momento in cui si utilizza una parola di controllo corrispondente a una macro dichiarata in questo modo, si ottiene l’espansione del suo contenuto. In altri termini, la parola di controllo diventa una forma abbreviata per scrivere un testo più articolato, che può contenere a sua volta altre sequenze di controllo, che vengono espanse solo all’ultimo momento. Si osservi l’esempio seguente: \def\resistenza{\valore{} ohm \tolleranza{} \%} \def\valore{100} \def\tolleranza{5} 25 resistenze \resistenza \par \def\valore{300} \def\tolleranza{1} 30 resistenze \resistenza \par \bye Si otterrà un testo simile a quello seguente, con cui si comprende il fatto che le parole di controllo ‘\valore’ e ‘\tolleranza’ vengono espanse per ultime: L’espansione di una parola di controllo del genere avviene in modo letterale, salvo naturalmente l’espansione successiva del suo contenuto, ma questo fatto significa che vengono riprodotte anche le interruzioni delle righe e gli spazi. Alle volte si preferisce strutturare il contenuto di una dichiarazione del genere, per cui si utilizzano dei commenti per evitare di dare un significato agli spazi che si inseriscono. Si osservi l’esempio precedente dopo una piccola modifica: \def\resistenza{ \valore{} ohm \tolleranza{} \%} \def\valore{100} \def\tolleranza{5} 25 resistenze \resistenza \par \def\valore{300} \def\tolleranza{1} 30 resistenze \resistenza \par \bye In questo caso, ciò che si ottiene è diverso, perché la parola di controllo ‘\resistenza’ si espande inserendo inizialmente una riga vuota, ovvero ciò che poi si traduce nell’inizio di un paragrafo nuovo: Per evitare questo tipo di inconveniente, si può mettere un commento all’inizio della riga vuota, che così perde questa sua particolarità: \def\resistenza{ % \valore{} ohm \tolleranza{} \%} Di solito, in queste situazioni si mette un commento anche dopo la parentesi graffa aperta: TeX: introduzione 2477 \def\resistenza{% % \valore{} ohm \tolleranza{} \%} Oltre a questo è da tenere in considerazione che nel momento dell’espansione, ciò che si ottiene non risulta contenuto in una zona separata; in altri termini, ciò che viene dichiarato o modificato all’interno di questa definizione, continua a valere anche al di fuori. Eventualmente, se si intende che l’espansione debba generare una zona isolata, vanno usate le parentesi graffe come già mostrato. Per esempio: \def\attenzione{{\bf ATTENZIONE!!!}} In questo caso, l’istruzione ‘\bf’ inizia la scrittura in neretto; così, la parola di controllo ‘\attenzione’ permette di inserire la scritta che si vede, in neretto, senza interferire con il testo successivo. Gli esempi usati fino a questo punto sono riconducibili all’idea di una funzione che non prevede parametri per la chiamata, ricevendo i dati attraverso variabili globali. Per dichiarare una macro in grado di ricevere dei parametri si usa una dichiarazione come quella seguente: [ [ ]]{espressione_stringa } \def\nome #1 #2... #9 In una dichiarazione del genere si possono indicare un massimo di nove parametri, rappresentati da ‘#1’, ‘#2’,... ‘#9’, che possono essere inseriti nella stringa contenuta tra le parentesi graffe. Volendo modificare l’esempio già visto, le cose si potrebbero semplificare nel modo seguente: \def\resistenza#1#2{#1 ohm #2 \%} 25 resistenze \resistenza{100}{5} \par 30 resistenze \resistenza{300}{1} \bye Nella dichiarazione, i simboli ‘#n ’ che si inseriscono all’interno del testo contenuto tra parentesi graffe possono essere indicati anche più volte, ottenendo sempre l’espansione del parametro n esimo corrispondente. È ormai evidente il modo in cui deve essere usata la parola di controllo che può essere chiamata con dei parametri: [ [...{parametro_n }]] \nome {parametro_1 } {parametro_2 } È importante sottolineare che, contrariamente a quanto si potrebbe immaginare, la stringa utilizzata in un parametro di scambio non può essere separata in paragrafi. Si osservi che molte macro predefinite di TeX isolano l’espressione stringa che restituiscono all’interno di un raggruppamento, in modo tale che ciò che si cambia al suo interno non si rifletta nel testo successivo. Di solito questo fatto è un comportamento «logico», o intuitivo, ma non si deve pensare che la definizione di una macro implichi automaticamente questa forma di isolamento. In pratica, il fatto di usare una parola di controllo del tipo ‘\nome {espressione }’, non significa implicitamente che quanto inserito come parametro non debba anche influenzare il testo successivo. 230.3.1 Chiamata di macroistruzioni che richiedono l’indicazione di parametri È stata mostrata la sintassi per la chiamata di una macro che richiede l’indicazione di uno o più parametri: TeX: introduzione 2478 [ [...{parametro_n }]] \nome {parametro_1 } {parametro_2 } Tuttavia, si tratta di una semplificazione. Infatti, i parametri possono anche non essere racchiusi tra parentesi graffe, ma in tal caso, il primo parametro sarà il primo carattere che segue. Si osservi l’esempio seguente, in cui si dichiara una macro con tre parametri e poi la si chiama senza raggruppare i parametri: \def\ciao#1#2#3{% Primo parametro: #1\par Secondo parametro: #2\par Terzo parametro: #3\par } \ciao, come stai? Nel capitolo 231 verrà mostrato l’uso di macro come ‘\‘’ che servono ad aggiungere un accento alla lettera successiva. Queste si usano solitamente senza circoscrivere la lettera che segue entro parentesi graffe. 230.4 Riferimenti ad altre parole o simboli di controllo È possibile creare dei riferimenti a una parola o a un simbolo di controllo, usando la sintassi seguente: \let\nome_nuovo =\nome In pratica, in questo modo si crea una parola di controllo alternativa a un’altra già esistente: ‘\nome_nuovo ’ può essere usato al posto di ‘\nome ’.6 Si osservi l’esempio: \newdimen\altezza \altezza=10cm \let\grandezza=\altezza \altezza=20cm La scatola ha una grandezza di \the\grandezza. \bye Si ottiene in pratica il testo dove 569,05511 punti corrispondono esattamente a 20 cm, ovvero l’ultimo valore assegnato alla lunghezza ‘\altezza’, a cui punta anche ‘\grandezza’. Tuttavia, se si fa un esperimento simile con una parola di controllo corrispondente a una macro definita con l’istruzione ‘\def’, il riferimento che si genera con l’istruzione ‘\let’ è quello che punta alla macro di quel momento, mentre una ridefinizione della parola di controllo di partenza non si riflette nel riferimento: \def\resistenza#1#2{#1 ohm #2 \%} \let\prova=\resistenza 25 resistenze \resistenza{100}{5} 25 resistenze \prova{100}{5} 6 Si possono creare delle alternative anche a simboli di controllo, ma in generale ciò non è conveniente. TeX: introduzione 2479 \def\resistenza#1#2{#2 ohm #1 \%} 30 resistenze \resistenza{300}{1} 30 resistenze \prova{300}{1} \bye Quello che si ottiene dalla composizione di questo esempio è il testo seguente: 230.5 Testo normale e ambienti matematici Una caratteristica molto importante di TeX è la distinzione tra due modalità di funzionamento. In pratica, si distingue un contesto «normale» da un contesto matematico. L’ambiente matematico si introduce e si conclude con il simbolo ‘$’ e in tale situazione diventano disponibili delle istruzioni che non si possono utilizzare al di fuori di questo ambito, mentre alcune istruzioni che erano disponibili prima non lo sono più. Per esempio, alcuni caratteri esistono solo nell’ambiente matematico; è già stato visto in che modo vanno indicate le parentesi graffe quando si scrive in un ambito normale, attraverso le istruzioni ‘$\{$’ e ‘$\}$’. In pratica, il dollaro iniziale e finale di queste istruzioni serve ad aprire e a chiudere l’ambiente matematico. 230.6 Modalità orizzontale e modalità verticale Nel suo lavoro di composizione, TeX distingue due situazioni, definite come modalità orizzontale e modalità verticale. Per comprendere la differenza tra queste due situazioni, occorre pensare alla struttura di ciò che si inserisce in una pagina. Ogni oggetto che viene inserito in una pagina è una scatola, con le sue dimensioni. Queste scatole si inseriscono a loro volta all’interno di altre; per esempio, una lettera è una scatola che si inserisce in una riga, ovvero un’altra scatola, che a sua volta si inserisce in un paragrafo, ovvero ancora un’altra scatola, ecc. In base al contesto, orizzontale o verticale, TeX si occupa di inserire spazi orizzontali o verticali: tra le lettere di una parola, tra le parole, tra le righe, tra i paragrafi, ecc. Quello che conta comprendere di tutto questo è che alcune istruzioni possono essere inserite solo in modalità orizzontale, altre solo in modalità verticale. Volendo sperimentare se un certo contesto si trovi in modalità orizzontale o verticale, si può realizzare la macro seguente e collocarla nel testo dove si ritiene opportuno; nella composizione finale si otterrà alternativamente la frase «modalità orizzontale», oppure «modalità verticale»: \def\verificamodo{% \ifvmode modalit\‘a verticale \else modalit\‘a orizzontale \fi} Nella sezione 230.7 viene spiegato l’uso dell’istruzione ‘\ifvmode’. TeX: introduzione 2480 230.7 Strutture di controllo Il linguaggio di TeX possiede una serie di strutture di controllo condizionali, in cui parte della condizione è implicita nel nome dell’istruzione con cui la si introduce. Questo insieme di strutture ha una sintassi comune riconducibile alla semplificazione seguente: [ ] \ifnome_condizione argomento testo_e_altre_istruzioni_se_vero \else testo_e_altre_istruzioni_se_falso \fi Spesso, per completare la struttura anche quando una delle due ipotesi non deve generare alcun risultato, si utilizza l’istruzione ‘\relax’, che rappresenta proprio l’operazione nulla. Nelle sezioni seguenti vengono descritte solo le strutture condizionali più comuni. 230.7.1 \ifodd È possibile verificare se un numero intero è dispari o pari con la struttura seguente: \ifodd n testo_e_altre_istruzioni_se_dispari \else testo_e_altre_istruzioni_se_pari \fi Di solito, al posto del numero n si inserisce l’istruzione ‘\pageno’ che restituisce il numero della pagina corrente, permettendo così di verificare se la pagina è dispari o pari: \ifodd \pageno testo_e_altre_istruzioni_se_pagina_dispari \else testo_e_altre_istruzioni_se_pagina_pari \fi 230.7.2 \ifmmode È possibile verificare se ci si trova in modalità normale o in modalità matematica con la struttura seguente: \ifmmode testo_e_altre_istruzioni_se_modalità_matematica \else testo_e_altre_istruzioni_se_modalità_normale \fi 230.7.3 \ifnum È possibile mettere a confronto due numeri con la struttura seguente: || \ifnum m = > <n testo_e_altre_istruzioni_se_confronto_valido \else testo_e_altre_istruzioni_se_confronto_non_valido \fi In pratica, il confronto può avvenire solo con gli operatori ‘=’, ‘>’ e ‘<’, per indicare rispettivamente se i due valori sono uguali, se il primo è maggiore del secondo oppure se il primo è minore del secondo. TeX: introduzione 2481 230.7.4 \ifhmode e \ifvmode È possibile verificare se la composizione si trova in modalità orizzontale o verticale con una delle due strutture seguenti: \ifhmode testo_e_altre_istruzioni_se_modalità_orizzontale \else testo_e_altre_istruzioni_se_modalità_verticale \fi \ifvmode testo_e_altre_istruzioni_se_modalità_verticale \else testo_e_altre_istruzioni_se_modalità_orizzontale \fi 230.8 Verifica del significato di un’istruzione elementare Per TeX, un’istruzione elementare può essere il singolo carattere di una parola, oppure una sequenza di controllo. Volendo comprendere il senso di qualcosa, si può verificare come intenda TeX questa o quell’istruzione. Per questo, occorre avviare la composizione indicando un file vuoto; per esempio, in un sistema Unix si potrebbe fare così: $ tex /dev/null[ Invio ] This is TeX, Version 3.14159 (Web2C 7.3.1) (/dev/null) * A questo punto, dall’invito, si può usare l’istruzione ‘\show’ nel modo seguente: \show istruzione_elementare Per esempio, ci si può domandare se il carattere ‘@’ abbia un significato particolare: *\show @[ Invio ] > the character @. <*> \show @ ? A questo punto, la composizione si ferma in attesa di altre indicazioni, mostrando un invito differente. Questo permette di comprendere anche che non conviene usare ‘\show’ in un file normale del quale si vuole ottenere la composizione, perché in quel punto ci sarebbe una sospensione con richiesta di intervento. A ogni modo, per proseguire basta premere [ Invio ], quindi si può chiedere di conoscere qualcosa di diverso: ?[ Invio ] *\show \TeX[ Invio ] In questo caso si vuole conoscere in cosa consiste la macro ‘\TeX’ ed ecco il risultato che si ottiene: > \TeX=macro: ->T\kern -.1667em\lower .5ex\hbox {E}\kern -.125emX. <*> \show \TeX ? Pertanto, questo significa che ‘\TeX’ è definita come: TeX: introduzione 2482 \def\TeX{T\kern -.1667em\lower .5ex\hbox {E}\kern -.125emX} Per completare l’esempio, conviene vedere come appare una macro che prevede l’indicazione di un parametro, come nel caso di ‘\‘’, che serve a mettere un accento grave su una lettera: ?[ Invio ] *\show \‘[ Invio ] > \‘=macro: #1->{\accent 18 #1}. <*> \show \‘ ? In pratica, la definizione originale è la seguente: \def\‘#1{{\accent 18 #1}} Per terminare l’uso interattivo basta inserire alla fine l’istruzione ‘\bye’: ?[ Invio ] *\bye[ Invio ] No pages of output. Transcript written on null.log. 230.9 Riferimenti • General documentation about (La)TeX <http://tex.loria.fr/english/general.html> • Michael Doob, A gentle introduction to TeX <http://www.ctan.org/tex-archive/info/gentle/gentle.pdf> • Daniel M. Zirin, TeX made easy, Using TeX with plain macro package, 1993, Zar Limited <http://www.loria.fr/services/tex/general/all.dvi> • D. R. Wilkins, Getting started with plain TeX, 1993 <http://www.loria.fr/services/tex/general/pllong.dvi> • D. R. Wilkins, Summary of commonly-used features of plain TeX, 1993 <http://www.loria.fr/services/tex/general/plshort.dvi> • TeX cookbook, 1989, MathPro Press <http://www.loria.fr/services/tex/general/cookbook.dvi> • Sorgenti della definizione del formato ‘tex’, contenuti nella directory ‘texmf/tex/ plain/base/’ di una distribuzione teTeX • Sorgenti della definizione del formato ‘latex’, contenuti nel file ‘texmf/tex/latex/ base/latex.ltx’ di una distribuzione teTeX • Claudio Beccari, LaTeX, Guida a un sistema di editoria elettronica, Hoepli, 1991, ISBN 88-203-1931-4 Appunti di informatica libera 2003.01.01 --- Copyright © 2000-2003 Daniele Giacomini -- daniele @ swlibero.org Capitolo 231 TeX: caratteri In condizioni normali, il testo scritto nel sorgente viene riprodotto nello stesso modo nella composizione finale, dopo essere stato reimpaginato opportunamente. Tuttavia, alcuni simboli hanno significati speciali, per cui si devono usare simboli di controllo al loro posto, inoltre le lettere accentate e altri caratteri che non fanno parte dell’ASCII standard non possono essere usati direttamente, per cui servono altri simboli o parole di controllo per generarli. A fianco di questo problema, nasce poi l’esigenza di poter scrivere utilizzando stili, forme e corpi differenti. 231.1 Caratteri speciali Come è già stato descritto nella tabella 230.1, alcuni caratteri hanno un significato speciale e non producono il simbolo corrispondente in fase di composizione. Per porre rimedio a questo problema e alla mancanza di altri caratteri, si usano generalmente delle sequenze di controllo. Tuttavia, dal momento che si distinguono due contesti di composizione differenti (quello normale e quello matematico), certi caratteri o certe sequenze di controllo esistono solo nella modalità matematica. In generale, salvo altra indicazione, si fa sempre riferimento alla modalità di composizione normale, per cui un carattere o una sequenza di controllo che può apparire solo in modalità matematica, viene mostrata generalmente delimitandola tra due simboli ‘$’. Per esempio, quando si afferma che le parentesi graffe si ottengono con le istruzioni ‘$\{$’ e ‘$\}$’, è chiaro che in modalità matematica non serve più la delimitazione con i simboli ‘$’. La tabella 231.1 riepiloga le sequenze di controllo per i caratteri speciali disponibili.1 Tabella 231.1. Elenco delle sequenze di controllo necessarie a ottenere i caratteri speciali che non richiedono la sovrapposizione di accenti. 1 Leggendo la tabella, è il caso di osservare che in condizioni normali, la sequenza di controllo ‘\$’ genera il simbolo del dollaro, mentre se il testo è in corsivo, si ottiene il simbolo della sterlina inglese. 2483 2484 " ' & ) - + 2 6 8 < A !B . 31 5 9 = > ? 5 ; A B TeX: caratteri ! $%! $%$ # $& ( *) , / 4 7 : @@@ * 01 5 ; ; 231.2 Accenti TeX ha la capacità di collocare un accento sopra ogni simbolo, anche se ciò che si ottiene può non avere senso per qualunque lingua. Questa apposizione di accenti si ottiene con sequenze di controllo che precedono la lettera da accentare. Quando si tratta di simboli di controllo, la lettera successiva può essere unita alla sequenza, mentre quando si tratta di parole di controllo occorre lasciare uno spazio di sicurezza. Per esempio, si scrive ‘\‘o’ per ottenere la lettera «ò», mentre si scrive ‘\c c’ per ottenere la lettera ‘ç’.2 La tabella 231.2 riepiloga le sequenze di controllo necessarie a ottenere tutti gli accenti disponibili, usando la lettera «o» come esempio. Tabella 231.2. Elenco delle sequenze di controllo necessarie a ottenere le lettere accentate. # 2 $ % !" Si osservi che in questo caso non si può usare un raggruppamento vuoto al posto dello spazio, perché l’accento risulterebbe spostato rispetto al centro della lettera.