Riforma delle macro per le funzioni, si riformatta un bel po' di roba.
[gapil.git] / filestd.tex
index a20d207aea09d97e4b69dfb9fd73ef0715b80d83..de338feb1a09b4740e1fe298c1947c5016e7d16d 100644 (file)
@@ -11,7 +11,7 @@ dell'interfaccia nell'ultima sezione.
 \section{Introduzione}
 \label{sec:file_stream_intro}
 
 \section{Introduzione}
 \label{sec:file_stream_intro}
 
-Come visto in \capref{cap:file_unix_interface} le operazioni di I/O sui file
+Come visto in \capref{cha:file_unix_interface} le operazioni di I/O sui file
 sono gestibili a basso livello con l'interfaccia standard unix, che ricorre
 direttamente alle system call messe a disposizione dal kernel.
 
 sono gestibili a basso livello con l'interfaccia standard unix, che ricorre
 direttamente alle system call messe a disposizione dal kernel.
 
@@ -46,11 +46,11 @@ di lettura e scrittura in blocchi di dimensioni appropriate all'ottenimento
 della massima efficienza.
 
 Per questo motivo l'interfaccia viene chiamata anche interfaccia dei
 della massima efficienza.
 
 Per questo motivo l'interfaccia viene chiamata anche interfaccia dei
-\textit{file stream}, dato che non è più necessario doversi preoccupare di dei
-dettagli della comunicazione con il tipo di hardware sottostante (come nel
-caso della dimensione dei blocchi del filesystem), ed un file può essere
-sempre considerato come composto da un flusso continuo (da cui il nome
-\textit{stream}) di dati.
+\textit{file stream}, dato che non è più necessario doversi preoccupare
+dei dettagli della comunicazione con il tipo di hardware sottostante
+(come nel caso della dimensione dei blocchi del filesystem), ed un file
+può essere sempre considerato come composto da un flusso continuo (da
+cui il nome \textit{stream}) di dati.
 
 A parte i dettagli legati alla gestione delle operazioni di lettura e
 scrittura (sia per quel che riguarda la bufferizzazione, che le
 
 A parte i dettagli legati alla gestione delle operazioni di lettura e
 scrittura (sia per quel che riguarda la bufferizzazione, che le
@@ -69,13 +69,12 @@ contengono tutte le informazioni necessarie a gestire le operazioni sugli
 stream, come la posizione corrente, lo stato del buffer e degli indicatori di
 stato e di fine del file.
 
 stream, come la posizione corrente, lo stato del buffer e degli indicatori di
 stato e di fine del file.
 
-Per questo motivo gli utenti non devono mai utilizzare direttamente o allocare
-queste strutture, ma usare sempre puntatori del tipo \type{FILE *} ottenuti
-dalla libreria stessa (tanto che in certi casi il termine di puntatore a file
-è diventato sinonimo di stream). 
-
-Tutte le funzioni della libreria che operano sui file accettano come parametri
-solo variabili di questo tipo, che diventa accessibile includendo l'header
+Per questo motivo gli utenti non devono mai utilizzare direttamente o
+allocare queste strutture, ma usare sempre puntatori del tipo \type{FILE
+  *} ottenuti dalla libreria stessa (tanto che in certi casi il termine
+di puntatore a file è diventato sinonimo di stream).  Tutte le funzioni
+della libreria che operano sui file accettano come parametri solo
+variabili di questo tipo, che diventa accessibile includendo l'header
 file \file{stdio.h}.
 
 
 file \file{stdio.h}.
 
 
@@ -111,9 +110,9 @@ dell'output di un programma con il semplice codice:
     fclose (stdout);
     stdout = fopen ("standard-output-file", "w");
 \end{lstlisting}
     fclose (stdout);
     stdout = fopen ("standard-output-file", "w");
 \end{lstlisting}
-ma in altri sistemi possono essere definite come macro, se si hanno
-problemi di portabilità e si vuole essere sicuri, diventa opportuno
-usare la funzione \func{freopen}.
+ma in altri sistemi queste variabili possono essere definite da macro, e
+se si hanno problemi di portabilità e si vuole essere sicuri, diventa
+opportuno usare la funzione \func{freopen}.
 
 
 \subsection{Le modalità di bufferizzazione}
 
 
 \subsection{Le modalità di bufferizzazione}
@@ -210,9 +209,10 @@ corrente in uno stream.
 \subsection{Apertura e chiusura di uno stream}
 \label{sec:file_fopen}
 
 \subsection{Apertura e chiusura di uno stream}
 \label{sec:file_fopen}
 
-Le funzioni che permettono di aprire uno stream sono tre\footnote{\func{fopen}
-  e \func{freopen} fanno parte dello standard ANSI C, \func{fdopen} è parte
-dello standard POSIX.1.}, i loro prototipi sono:
+Le funzioni che si possono usare per aprire uno stream sono solo
+tre\footnote{\func{fopen} e \func{freopen} fanno parte dello standard
+  ANSI C, \func{fdopen} è parte dello standard POSIX.1.}, i loro
+prototipi sono:
 \begin{functions}
   \headdecl{stdio.h}
   \funcdecl{FILE * fopen(const char * path, const char *mode)}
 \begin{functions}
   \headdecl{stdio.h}
   \funcdecl{FILE * fopen(const char * path, const char *mode)}
@@ -223,30 +223,34 @@ dello standard POSIX.1.}, i loro prototipi sono:
   stream)}
   Apre il file specificato da \param{path} associandolo allo stream
   specificato da \param{stream}, se questo è già aperto prima lo chiude.
   stream)}
   Apre il file specificato da \param{path} associandolo allo stream
   specificato da \param{stream}, se questo è già aperto prima lo chiude.
-
-  Le funzioni ritornano un puntatore valido in caso di successo e \macro{NULL}
-  in caso di errore, in tal caso \var{errno} viene settata al valore ricevuto
-  dalla funzione sottostante di cui è fallita l'esecuzione.
   
   
-  Gli errori pertanto possono essere quelli di \func{malloc} per tutte e tre
-  le funzioni, quelli \func{open} per \func{fopen}, quelli di \func{fcntl} per
-  \func{fdopen} e quelli di \func{fopen}, \func{fclose} e \func{fflush} per
-  \func{freopen}. 
+  \bodydesc{Le funzioni ritornano un puntatore valido in caso di
+    successo e \macro{NULL} in caso di errore, in tal caso \var{errno}
+    viene settata al valore ricevuto dalla funzione sottostante di cui è
+    fallita l'esecuzione.
+  
+    Gli errori pertanto possono essere quelli di \func{malloc} per tutte
+    e tre le funzioni, quelli \func{open} per \func{fopen}, quelli di
+    \func{fcntl} per \func{fdopen} e quelli di \func{fopen},
+    \func{fclose} e \func{fflush} per \func{freopen}.}
 \end{functions}
 
 \end{functions}
 
-Normalmente la funzione che si usa per aprire uno stream è \func{fopen}, essa
-apre il file specificato nella modalità specificata da \param{mode} che è una
-delle stringhe elencate in \tabref{tab:file_fopen_mode}. 
+Normalmente la funzione che si usa per aprire uno stream è \func{fopen},
+essa apre il file specificato nella modalità specificata da
+\param{mode}, che è una stringa che deve iniziare con almeno uno dei
+valori indicati in \tabref{tab:file_fopen_mode} (sono possibili varie
+estensioni che vedremo in seguito).
 
 
-L'uso di \func{freopen} è in genere per redirigere uno dei tre file standard
-(vedi \secref{sec:file_std_stream}): il file \param{path} viene associato a
-\param{stream} e se questo è uno stream aperto prima viene chiuso.  
+L'uso più comune di \func{freopen} è per redirigere uno dei tre file
+standard (vedi \secref{sec:file_std_stream}): il file \param{path} viene
+associato a \param{stream} e se questo è uno stream già aperto viene
+preventivamente chiuso.
 
 
-Infine \func{fdopen} viene usato per associare uno stream ad un file
-descriptor esistente ottenuto tramite una altra funzione (come \func{open},
-\func{dup}, \func{pipe}) e serve quando si vogliono usare gli stream con file
-speciali come le fifo od i socket, che non possono essere aperti con le
-funzioni delle librerie standard del C.
+Infine \func{fdopen} viene usata per associare uno stream ad un file
+descriptor esistente ottenuto tramite una altra funzione (ad esempio con
+una \func{open}, una \func{dup}, o una \func{pipe}) e serve quando si
+vogliono usare gli stream con file come le fifo o i socket, che non
+possono essere aperti con le funzioni delle librerie standard del C.
 
 \begin{table}[htb]
   \centering
 
 \begin{table}[htb]
   \centering
@@ -255,25 +259,26 @@ funzioni delle librerie standard del C.
     \textbf{Valore} & \textbf{Significato}\\
     \hline
     \hline
     \textbf{Valore} & \textbf{Significato}\\
     \hline
     \hline
-    \texttt{r} & Il file viene aperto in sola lettura; lo stream è posizionato
-    all'inizio del file.\\
-    \texttt{r+} & Il file viene aperto in lettura e scrittura; lo stream è
-    posizionato all'inizio del file. \\
+    \texttt{r} & Il file viene aperto, l'accesso viene posto in sola
+    lettura, lo stream è posizionato all'inizio del file.\\
+    \texttt{r+} & Il file viene aperto, l'accesso viene posto in lettura e
+    scrittura, lo stream è posizionato all'inizio del file. \\
 %    \hline
 %    \hline
-    \texttt{w} & Il file viene troncato a lunghezza nulla (o creato se non 
-    esiste), ed aperto in sola lettura; lo stream è posizionato all'inizio del
-    file.\\
-    \texttt{w+} & Il file viene troncato a lunghezza nulla (o creato se non
-    esiste), ed aperto in scrittura e lettura; lo stream è posizionato 
-    all'inizio del file.\\
+    \texttt{w} & Il file viene aperto e troncato a lunghezza nulla (o
+    creato se non esiste), l'accesso viene posto in sola scrittura, lo
+    stream è posizionato all'inizio del file.\\
+    \texttt{w+} & Il file viene aperto e troncato a lunghezza nulla (o
+    creato se non esiste), l'accesso viene posto in scrittura e lettura,
+    lo stream è posizionato all'inizio del file.\\
 %    \hline
 %    \hline
-    \texttt{a} & Il file è aperto in \textit{append mode} in sola scrittura
-    (o creato se non esiste). \\
-    \texttt{a+} & Il file è aperto in \textit{append mode} in lettura e 
-    scrittura (o creato se non esiste). \\
+    \texttt{a} & Il file viene aperto (o creato se non esiste) in
+    \textit{append mode}, l'accesso viene posto in sola scrittura. \\
+    \texttt{a+} & Il file viene aperto (o creato se non esiste) in
+    \textit{append mode}, l'accesso viene posto in lettura e scrittura. \\
     \hline
   \end{tabular}
     \hline
   \end{tabular}
-  \caption{Modalità di apertura di uno stream}
+  \caption{Modalità di apertura di uno stream dello standard ANSI C che
+    sono sempre presenti in qualunque sistema POSIX}
   \label{tab:file_fopen_mode}
 \end{table}
 
   \label{tab:file_fopen_mode}
 \end{table}
 
@@ -286,13 +291,27 @@ distinguere i file binari dai file di testo; in un sistema POSIX questa
 distinzione non esiste e il valore viene accettato solo per
 compatibilità, ma non ha alcun effetto.
 
 distinzione non esiste e il valore viene accettato solo per
 compatibilità, ma non ha alcun effetto.
 
+Le \acr{glibc} supportano alcune estensioni, queste devono essere sempre
+indicate dopo aver specificato il \param{mode} con uno dei valori di
+\tabref{tab:file_fopen_mode}. L'uso del carattere \texttt{x} serve per
+evitare di sovrascrivere un file già esistente (è analoga all'uso
+dell'opzione \macro{O\_EXCL} in \func{open}), se il file specificato già
+esiste e si aggiunge questo carattere a \param{mode} la \func{fopen}
+fallisce. 
+
+Un'altra estensione serve a supportare la localizzazione, quando si
+aggiunge a \param{mode} una stringa della forma \verb|",ccs=STRING"| il
+valore \verb|STRING| è considerato il nome di una codifica dei caratteri
+e \func{fopen} marca il file per l'uso dei caratteri estesi e abilita le
+opportune funzioni di conversione in lettura e scrittura.
+
 Inoltre nel caso si usi \func{fdopen} i valori specificati da
 \param{mode} devono essere compatibili con quelli con cui il file
 descriptor è stato aperto. Inoltre i modi \cmd{w} e \cmd{w+} non
 troncano il file. La posizione nello stream viene settata a quella
 corrente nel file descriptor, e le variabili di errore e di fine del
 Inoltre nel caso si usi \func{fdopen} i valori specificati da
 \param{mode} devono essere compatibili con quelli con cui il file
 descriptor è stato aperto. Inoltre i modi \cmd{w} e \cmd{w+} non
 troncano il file. La posizione nello stream viene settata a quella
 corrente nel file descriptor, e le variabili di errore e di fine del
-file sono cancellate. Il file non viene duplicato e verrà chiuso alla
-chiusura dello stream.
+file (vedi \secref{sec:file_io}) sono cancellate. Il file non viene
+duplicato e verrà chiuso alla chiusura dello stream.
 
 I nuovi file saranno creati secondo quanto visto in
 \secref{sec:file_ownership} ed avranno i permessi di accesso settati al
 
 I nuovi file saranno creati secondo quanto visto in
 \secref{sec:file_ownership} ed avranno i permessi di accesso settati al
@@ -305,7 +324,7 @@ di messo una bufferizzazione; per questo motivo lo standard ANSI C
 richiede che ci sia una operazione di posizionamento fra una operazione
 di output ed una di input o viceversa (eccetto il caso in cui l'input ha
 incontrato la fine del file), altrimenti una lettura può ritornare anche
 richiede che ci sia una operazione di posizionamento fra una operazione
 di output ed una di input o viceversa (eccetto il caso in cui l'input ha
 incontrato la fine del file), altrimenti una lettura può ritornare anche
-il risultato di scritture precedenti l'ultima effettuata.
+il risultato di scritture precedenti l'ultima effettuata. 
 
 Per questo motivo è una buona pratica (e talvolta necessario) far seguire ad
 una scrittura una delle funzioni \func{fflush}, \func{fseek}, \func{fsetpos} o
 
 Per questo motivo è una buona pratica (e talvolta necessario) far seguire ad
 una scrittura una delle funzioni \func{fflush}, \func{fseek}, \func{fsetpos} o
@@ -329,11 +348,12 @@ Uno stream viene chiuso con la funzione \func{fclose} il cui prototipo 
   funzione che è fallita (\func{close}, \func{write} o \func{fflush}).
 \end{prototype}
 
   funzione che è fallita (\func{close}, \func{write} o \func{fflush}).
 \end{prototype}
 
-La funzione effettua uno scarico di tutti i dati presenti nei buffer di uscita
-e scarta tutti i dati in ingresso, se era stato allocato un buffer per lo
-stream questo verrà rilasciato. La funzione effettua lo scarico solo per i
-dati presenti nei buffer in user space usati dalle \acr{glibc}; se si essere
-sicuri che il kernel forzi la scrittura su disco occorrerà effettuare . 
+La funzione effettua uno scarico di tutti i dati presenti nei buffer di
+uscita e scarta tutti i dati in ingresso, se era stato allocato un
+buffer per lo stream questo verrà rilasciato. La funzione effettua lo
+scarico solo per i dati presenti nei buffer in user space usati dalle
+\acr{glibc}; se si vuole essere sicuri che il kernel forzi la scrittura
+su disco occorrerà effettuare una \func{sync}.
 
 Linux supporta, come estensione implementata dalle \acr{glibc}, anche una
 altra funzione, \func{fcloseall}, che serve a chiudere tutti i file, il suo
 
 Linux supporta, come estensione implementata dalle \acr{glibc}, anche una
 altra funzione, \func{fcloseall}, che serve a chiudere tutti i file, il suo
@@ -358,25 +378,25 @@ Una delle caratteristiche pi
 ricchezza delle funzioni disponibili per le operazioni di lettura e
 scrittura sui file. Sono infatti previste ben tre diverse modalità
 modalità di input/output non formattato:
 ricchezza delle funzioni disponibili per le operazioni di lettura e
 scrittura sui file. Sono infatti previste ben tre diverse modalità
 modalità di input/output non formattato:
-\begin{enumerate}
+\begin{enumerate*}
 \item\textsl{binario} in cui legge/scrive un blocco di dati alla
   volta, vedi \secref{sec:file_binary_io}.
 \item\textsl{binario} in cui legge/scrive un blocco di dati alla
   volta, vedi \secref{sec:file_binary_io}.
-\item\textsl{di linea} in cui si legge/scrive una linea (terminata dal
-  carattere di newline \verb|\n|) alla volta, vedi
-  \secref{sec:file_line_io}.
 \item\textsl{a caratteri} in cui si legge/scrive un carattere alla
   volta (con la bufferizzazione gestita automaticamente dalla libreria),
   vedi \secref{sec:file_char_io}.
 \item\textsl{a caratteri} in cui si legge/scrive un carattere alla
   volta (con la bufferizzazione gestita automaticamente dalla libreria),
   vedi \secref{sec:file_char_io}.
-\end{enumerate}
+\item\textsl{di linea} in cui si legge/scrive una linea (terminata dal
+  carattere di newline \verb|\n|) alla volta, vedi
+  \secref{sec:file_line_io}.
+\end{enumerate*}
 ed inoltre la modalità di input/output formattato.
 
 ed inoltre la modalità di input/output formattato.
 
-A differenza dell'interfaccia dei file descriptor il raggiungimento della fine
-del file è considerato un errore, e viene notificato come tale dai valori di
-uscita delle varie funzioni; nella maggior parte dei casi questo avviene con
-la restituzione del valore intero (di tipo \type{int}) \macro{EOF}\footnote{la
-  costante deve essere negativa, le \acr{glibc} usano -1, altre
-  implementazioni possono avere valori diversi.}  definito anch'esso
-nell'header \func{stdlib.h}.
+A differenza dell'interfaccia dei file descriptor, con gli stream il
+raggiungimento della fine del file è considerato un errore, e viene
+notificato come tale dai valori di uscita delle varie funzioni. Nella
+maggior parte dei casi questo avviene con la restituzione del valore
+intero (di tipo \type{int}) \macro{EOF}\footnote{la costante deve essere
+  negativa, le \acr{glibc} usano -1, altre implementazioni possono avere
+  valori diversi.}  definito anch'esso nell'header \func{stdlib.h}.
 
 Dato che le funzioni dell'interfaccia degli stream sono funzioni di libreria
 che si appoggiano a delle system call, esse non settano direttamente la
 
 Dato che le funzioni dell'interfaccia degli stream sono funzioni di libreria
 che si appoggiano a delle system call, esse non settano direttamente la
@@ -395,7 +415,7 @@ mantengono per ogni stream almeno due flag all'interno dell'oggetto
 \type{FILE}, il flag di \textit{end-of-file}, che segnala che si è
 raggiunta la fine del file in lettura, e quello di errore, che segnala
 la presenza di un qualche errore nelle operazioni di input/output;
 \type{FILE}, il flag di \textit{end-of-file}, che segnala che si è
 raggiunta la fine del file in lettura, e quello di errore, che segnala
 la presenza di un qualche errore nelle operazioni di input/output;
-questi flag possono essere riletti dalle funzioni:
+questi due flag possono essere riletti dalle funzioni:
 \begin{functions}
   \headdecl{stdio.h}
   \funcdecl{int feof(FILE *stream)}
 \begin{functions}
   \headdecl{stdio.h}
   \funcdecl{int feof(FILE *stream)}
@@ -413,7 +433,7 @@ ogni volta che si chiama una funzione di libreria.
 
 Entrambi i flag (di errore e di end-of-file) possono essere cancellati usando
 la funzione \func{clearerr}, il cui prototipo è:
 
 Entrambi i flag (di errore e di end-of-file) possono essere cancellati usando
 la funzione \func{clearerr}, il cui prototipo è:
-\begin{prototype}{stdio.h}{void clearerr( FILE *stream)}
+\begin{prototype}{stdio.h}{void clearerr(FILE *stream)}
   Cancella i flag di errore ed end-of-file di \param{stream}. 
 \end{prototype}
 \noindent in genere si usa questa funziona una volta che si sia identificata e
   Cancella i flag di errore ed end-of-file di \param{stream}. 
 \end{prototype}
 \noindent in genere si usa questa funziona una volta che si sia identificata e
@@ -425,19 +445,22 @@ cos
 \label{sec:file_binary_io}
 
 La prima modalità di input/output non formattato ricalca quella della
 \label{sec:file_binary_io}
 
 La prima modalità di input/output non formattato ricalca quella della
-intefaccia dei file descriptor, e provvede semplicemente la scrittura e
-la lettura dei dati da un buffer verso un file e vicecersa. In generale
+interfaccia dei file descriptor, e provvede semplicemente la scrittura e
+la lettura dei dati da un buffer verso un file e viceversa. In generale
 questa è la modalità che si usa quando si ha a che fare con dati non
 formattati. Le due funzioni che si usano per l'I/O binario sono:
 \begin{functions}
   \headdecl{stdio.h} 
 questa è la modalità che si usa quando si ha a che fare con dati non
 formattati. Le due funzioni che si usano per l'I/O binario sono:
 \begin{functions}
   \headdecl{stdio.h} 
-  \funcdecl{size\_t fread(void * ptr, size\_t size,
-    size\_t nmemb, FILE * stream)} 
-  \funcdecl{size\_t fwrite(const void *
-    ptr, size\_t size, size\_t nmemb, FILE * stream)}
+  
+  \funcdecl{size\_t fread(void * ptr, size\_t size, size\_t nmemb, FILE
+    * stream)}
+  
+  \funcdecl{size\_t fwrite(const void * ptr, size\_t size, size\_t
+    nmemb, FILE * stream)}
   
   Le funzioni rispettivamente leggono e scrivono \param{nmemb} elementi
   
   Le funzioni rispettivamente leggono e scrivono \param{nmemb} elementi
-  di dimensione \param{size} dal buffer \param{ptr} al file \param{stream}.
+  di dimensione \param{size} dal buffer \param{ptr} al file
+  \param{stream}.
   
   Entrambe le funzioni ritornano il numero di elementi letti o scritti,
   in caso di errore o fine del file viene restituito un numero di
   
   Entrambe le funzioni ritornano il numero di elementi letti o scritti,
   in caso di errore o fine del file viene restituito un numero di
@@ -479,28 +502,221 @@ int WriteStruct(FILE * stream, struct histogram * histo, size_t nelem)
 }
 \end{lstlisting}
 in cui si specifica la dimensione dell'intera struttura ed un solo
 }
 \end{lstlisting}
 in cui si specifica la dimensione dell'intera struttura ed un solo
-elemento. In realtà quello che conta nel trasferimento dei dati sono le
-dimensioni totali, che sono sempre pari al prodotto \func{size * nelem},
-la sola differenza è che le funzioni non ritornano il numero di bytes
-scritti, ma il numero di elementi. 
+elemento. 
 
 
-La funzione \func{fread} legge sempre un numero intero di elementi, se
-si ha un errore o si incontra la fine del file l'oggetto letto
-parzialmente viene scartato
+In realtà quello che conta nel trasferimento dei dati sono le dimensioni
+totali, che sono sempre pari al prodotto \func{size * nelem}; la sola
+differenza è che le funzioni non ritornano il numero di byte scritti,
+ma il numero di elementi.
 
 
+La funzione \func{fread} legge sempre un numero intero di elementi, se
+incontra la fine del file l'oggetto letto parzialmente viene scartato
+(lo stesso avviene in caso di errore). In questo caso la posizione dello
+stream viene settata alla fine del file (e non a quella corrispondente
+alla quantità di dati letti).
+
+In caso di errore (o fine del file per \func{fread}) entrambe le
+funzioni restituiscono il numero di oggetti effettivamente letti o
+scritti, che sarà inferiore a quello richiesto. Contrariamente a quanto
+avviene per i file descriptor, questo segnala una condizione di errore e
+occorrerà usare \func{feof} e \func{ferror} per stabilire la natura del
+problema.
+
+Benché queste funzioni assicurino la massima efficienza per il
+salvataggio dei dati, i dati memorizzati attraverso di esse presentano
+lo svantaggio di dipendere strettamente dalla piattaforma di sviluppo
+usata ed in genere possono essere riletti senza problemi solo dallo
+stesso programma che li ha prodotti.
+
+Infatti diversi compilatori possono eseguire ottimizzazioni diverse
+delle strutture dati e alcuni compilatori (come il \cmd{gcc}) possono
+anche scegliere se ottimizzare l'occupazione di spazio, impacchettando
+più strettamente i dati, o la velocità inserendo opportuni
+\textit{padding} per l'allineamento dei medesimi generando quindi output
+binari diversi. Inoltre altre incompatibilità si possono presentare
+quando entrano in gioco differenze di architettura hardware, come la
+dimensione del bus o la modalità di ordinamento dei bit o il formato
+delle variabili in floating point.
+
+Per questo motivo quando si usa l'input/output binario occorre sempre
+essere prendere le opportune precauzioni (in genere usare un formato di
+più alto livello che permetta di recuperare l'informazione completa),
+per assicurarsi che versioni diverse del programma siano in grado di
+rileggere i dati tenendo conto delle eventuali differenze.
+
+Le \acr{glibc} definiscono altre due funzioni per l'I/O binario, che
+evitano il lock implicito dello stream, usato per dalla librerie per la
+gestione delle applicazioni multi-thread (si veda
+\secref{sec:file_stream_thread} per i dettagli).
 
 
-Benché queste funzioni assicurino 
+\begin{functions}
+  \headdecl{stdio.h} 
+  
+  \funcdecl{size\_t fread\_unlocked(void * ptr, size\_t size, size\_t
+    nmemb, FILE * stream)}
+  
+  \funcdecl{size\_t fwrite\_unlocked(const void * ptr, size\_t size,
+    size\_t nmemb, FILE * stream)}
+  
+  Le funzioni sono identiche alle analoghe \func{fread} e \func{fwrite}
+  ma non acquisiscono il lock implicito sullo stream.
+\end{functions}
+\noindent entrambe le funzioni sono estensioni GNU previste solo dalle
+\acr{glibc}.
 
 
 
 
-\subsection{Input/output a caratteri singoli}
+\subsection{Input/output a caratteri}
 \label{sec:file_char_io}
 
 \label{sec:file_char_io}
 
+La seconda modalità di input/output è quella a caratteri, in cui si
+trasferisce un carattere alla volta.  Le funzioni per la lettura a
+caratteri sono tre, \func{fgetc}, \func{getc} e \func{getchar}, i
+rispettivi prototipi sono:
+\begin{functions}
+  \headdecl{stdio.h} 
+
+  \funcdecl{int getc(FILE *stream)} Legge un byte da \param{stream} e lo
+  restituisce come intero. In genere è implementata come una macro. 
+
+  \funcdecl{int fgetc(FILE *stream)} Legge un byte da \param{stream} e lo
+  restituisce come intero. È una sempre una funzione.
+  
+  \funcdecl{int getchar(void)} è equivalente a \func{getc(stdin)}.
+  
+  \bodydesc{Tutte queste funzioni leggono un byte alla volta, che viene
+    restituito come intero; in caso di errore o fine del file il valore
+    di ritorno è \macro{EOF}.}
+\end{functions}
+
+A parte \func{getchar}, che si usa in genere per leggere un carattere da
+tastiera, le altre due funzioni sono sostanzialmente equivalenti. La
+differenza è che \func{gets} è ottimizzata al massimo e normalmente
+viene implementata con una macro, per cui occorre stare attenti a cosa
+le si passa come argomento, infatti \param{stream} può essere valutato
+più volte nell'esecuzione, e non viene passato in copia con il
+meccanismo visto in \secref{sec:proc_var_passing}; per questo motivo se
+si passa una espressione si possono avere effetti indesiderati.
+
+Invece \func{fgets} è assicurata essere sempre una funzione, per questo
+motivo la sua esecuzione normalmente è più lenta per via dell'overhead
+della chiamata, ma è altresì possibile ricavarne l'indirizzo, che può
+essere passato come parametro ad un altra funzione (e non si hanno i
+problemi accennati in precedenza con \param{stream}).
+
+Le tre funzioni restituiscono tutte un \type{unsigned char} convertito
+ad \type{int} (si usa \type{unsigned char} in modo da evitare
+l'espansione del segno). In questo modo il valore di ritorno è sempre
+positivo, tranne in caso di errore o fine del file.
+
+Nelle estenzioni GNU che provvedono la localizzazione sono definite tre
+funzioni equivalenti alle precedenti che invece di un carattere di un
+byte restituiscono un carattere in formato esteso (cioè di tipo
+\type{wint\_t}, il loro prototipo è:
+\begin{functions}
+  \headdecl{stdio.h} 
+  
+  \funcdecl{wint\_t getwc(FILE *stream)} Legge un carattere esteso da
+  \param{stream}. In genere è implementata come una macro.
+  
+  \funcdecl{wint\_t fgetwc(FILE *stream)} Legge un carattere esteso da
+  \param{stream} È una sempre una funzione.
+  
+  \funcdecl{wint\_t getwchar(void)} è equivalente a \func{getwc(stdin)}.
+  
+  \bodydesc{Tutte queste funzioni leggono un carattere alla volta, in
+    caso di errore o fine del file il valore di ritorno è \macro{WEOF}.}
+\end{functions}
+
+Per scrivere un carattere si possono usare tre funzioni analoghe alle
+precedenti usate per leggere: \func{putc}, \func{fputc} e
+\func{putchar}; i loro prototipi sono:
+\begin{functions}
+  \headdecl{stdio.h} 
+  
+  \funcdecl{int putc(int c, FILE *stream)} Scrive il carattere \param{c}
+  su \param{stream}. In genere è implementata come una macro.
+  
+  \funcdecl{int fputc(FILE *stream)} Scrive il carattere \param{c} su
+  \param{stream}. È una sempre una funzione.
+  
+  \funcdecl{int putchar(void)} è equivalente a \func{putc(stdin)}.
+  
+  \bodydesc{Le funzioni scrivono sempre un carattere alla volta, il cui
+    valore viene restituito in caso di successo; in caso di errore o
+    fine del file il valore di ritorno è \macro{EOF}.}
+\end{functions}
+
+Tutte queste funzioni scrivono sempre un byte alla volta, anche se
+prendono come parametro un \type{int} (che pertanto deve essere ottenuto
+con un cast da un \type{unsigned char}). Anche il valore di ritorno è
+sempre un intero; in caso di errore o fine del file il valore di ritorno
+è \macro{EOF}.
+
+Come nel caso dell'I/O binario le \acr{glibc} provvedono per ciascuna
+delle funzioni precedenti una seconda funzione, il cui nome è ottenuto
+aggiungendo un \func{\_unlocked}, che esegue esattamente le stesse
+operazioni evitando però il lock implicito dello stream.
+
+Per compatibilità con SVID sono provviste anche due funzioni per leggere
+e scrivere una \textit{word} (che è sempre definita come \type{int}); i
+loro prototipi sono:
+\begin{functions}
+  \headdecl{stdio.h} 
+  
+  \funcdecl{int getw(FILE *stream)} Legge una parola da \param{stream}.
+  \funcdecl{int putw(int w, FILE *stream)} Scrive la parola \param{w} su
+  \param{stream}.
+  
+  \bodydesc{Le funzioni restituiscono la parola \param{w}, o \macro{EOF}
+    in caso di errore o di fine del file.}
+\end{functions}
+\noindent l'uso di queste funzioni è deprecato in favore dell'uso di
+\func{fread} e \func{fwrite}, in quanto non è possibile distinguere il
+valore -1 da una condizione di errore che restituisce \macro{EOF}.
+
+Una degli usi più frequenti dell'input/output a caratteri è nei
+programmi di \textit{parsing} in cui si analizza il testo; in questo
+contesto diventa utile poter analizzare il carattere successivo da uno
+stream senza estrarlo effettivamente (la tecnica è detta \textit{peeking
+  ahead}) in modo che il programma possa regolarsi sulla base avendo
+dato una \textsl{sbirciatina} a quello che viene dopo. 
+
+Nel nostro caso questo tipo di comportamento può essere realizzato prima
+leggendo il carattere, e poi rimandandolo indietro, cosicchè ridiventi
+disponibile per una lettura successiva; la funzione che inverte la
+lettura si chiama \func{ungetc} ed il suo prototipo è:
+\begin{prototype}{stdio.h}{int ungetc(int c, FILE *stream)}
+  Cancella i flag di errore ed end-of-file di \param{stream}. 
+\end{prototype}
+
+
 
 
 
 \subsection{Input/output di linea}
 \label{sec:file_line_io}
 
 
 
 
 \subsection{Input/output di linea}
 \label{sec:file_line_io}
 
+La terza ed ultima modalità di input/output non formattato è quello di
+linea, in cui legge o scrive una riga alla volta; questa è una modalità
+molto usata, ma che presenta le caratteristiche più controverse.
+
+Le funzioni per leggere una linea sono sostazialmente due, \func{gets} e
+\func{fgets}, i rispettivi prototipi sono:
+\begin{functions}
+  \headdecl{stdio.h} 
+  
+  \funcdecl{char * gets(char * string)} Scrive su \param{string} una
+  linea letta da \var{stdin}.
+  
+  \funcdecl{char * fgets(char * string, int size, FILE *stream)}
+  Scrive su \param{string} la linea letta da \param{stream} per un
+  massimo di \param{size} byte.
+  
+  \bodydesc{Le funzioni restituiscono della stringa letta o \macro{NULL}
+    in caso di errore.}
+\end{functions}
+
+
 
 \subsection{Input/output formattato}
 \label{sec:file_formatted_io}
 
 \subsection{Input/output formattato}
 \label{sec:file_formatted_io}
@@ -514,9 +730,9 @@ Bench
 \section{Funzioni avanzate}
 \label{sec:file_stream_adv_func}
 
 \section{Funzioni avanzate}
 \label{sec:file_stream_adv_func}
 
-In questa sezione esamineremo le funzioni che permettono di controllare alcune
-caratteristiche più particolari degli stream, come la lettura degli attributi,
-le modalità di bufferizzazione, etc.
+In questa sezione esamineremo le funzioni che permettono di controllare
+alcune caratteristiche più particolari degli stream, come la lettura
+degli attributi, le modalità di bufferizzazione, etc.
 
 
 \subsection{Le funzioni di controllo}
 
 
 \subsection{Le funzioni di controllo}
@@ -530,7 +746,7 @@ derivate da Solaris, che permettono di ottenere informazioni utili.
 In certi casi può essere necessario sapere se un certo stream è accessibile in
 lettura o scrittura. In genere questa informazione non è disponibile, e si
 deve ricordare come il file è stato aperto. La cosa può essere complessa se le
 In certi casi può essere necessario sapere se un certo stream è accessibile in
 lettura o scrittura. In genere questa informazione non è disponibile, e si
 deve ricordare come il file è stato aperto. La cosa può essere complessa se le
-operazioni vengono effettuate un una subroutine, che a questo punto
+operazioni vengono effettuate in una subroutine, che a questo punto
 necessiterà di informazioni aggiuntive rispetto al semplice puntatore allo
 stream; questo può essere evitato con le due funzioni \func{\_\_freadable} e
 \func{\_\_fwritable} i cui prototipi sono:
 necessiterà di informazioni aggiuntive rispetto al semplice puntatore allo
 stream; questo può essere evitato con le due funzioni \func{\_\_freadable} e
 \func{\_\_fwritable} i cui prototipi sono:
@@ -577,6 +793,34 @@ serie di funzioni che permettono di controllare il comportamento degli
 stream; se non si è 
 
 
 stream; se non si è 
 
 
+\subsection{Gli stream e i thread}
+\label{sec:file_stream_thread}
+
+Gli stream possono essere usati in applicazioni multi-thread allo stesso
+modo in cui sono usati nelle applicazioni normali, ma si deve essere
+consapovoli delle possibili complicazioni anche quando non si usano i
+thread, dato che l'implementazione delle librerie è influenzata
+pesantemente dalle richieste necessarie per garantirne l'uso coi thread.
+
+
+
+\begin{functions}
+  \headdecl{stdio.h}
+  
+  \funcdecl{void flockfile(FILE * stream)} Esegue l'acquisizione del
+  lock dello stream \param{stream}, bloccandosi in caso il lock non
+  disponibile. 
+  
+  \funcdecl{int ftrylockfile(FILE * stream)} Tenta l'acquisizione del
+  lock dello stream \param{stream}, senza bloccarsi in caso il lock non sia
+  disponibile. Ritorna zero in caso di acquisizione del lock, diverso da
+  zero altrimenti.
+  
+  \funcdecl{void funlockfile(FILE * stream)} Rilascia il lock dello
+  stream \param{stream}.
+\end{functions}
+
+
 \subsection{Dettagli dell'implementazione}
 \label{sec:file_stream_details}
 
 \subsection{Dettagli dell'implementazione}
 \label{sec:file_stream_details}