Newsgroup: it.comp.lang.c
Titolo: sostituzione tag all'interno di un file

Ciao a tutto il NG,
questa domanda è inerente al solo linguaggio ANSI C, non è vincolata
da sistemi operativi o altre librerie (windoze, unix, ...), non avrei
postato qui altrimenti.
Ho la necessità di fare un parse di una serie di tag, stile html
all'interno di un file di input.
Il mio programma riceve un file in ingresso e produce su stdout lo
stesso file con le sostituzioni ove necessario.
esempio:
"
<inizio variabile fine> questo è un file di prova <inizio variabile
fine>
seconda <inizio A fine> riga
terza riga
ecc.. ecc..
"
e mettiamo che abbia due "variabili" che si chiamano:
"variabile" = abc
"A" = 123
vorrei ottenere
"
abc questo è un file di prova abc
seconda 123 riga
terza riga
ecc.. ecc..
"
Quello che devo fare è abbastanza semplice da descrivere a parole, in
pratica la parte di codice non è così immediata, c'è qualcuno che mi
sa dire se conosce qualche cosa di già fatto, un esempio, una libreria
regexp o qualcosa che mi possa aiutare.
Inoltre non è che posso fare una cosa del tipo: "carico tutto in
memoria in una char* e vado a fare ricerche li", il file in ingresso
può essere di dimensioni elevate, inoltre quello che faccio deve
rientrare all'interno di un programma che sto facendo
Sto scrivendo del gran codice ma la questione non è banale, c'è
qualcuno che mi sa dare qualche suggerimento ?
Grazie in anticipo per le risposte
Ben

 regexp o qualcosa che mi possa aiutare.
Una libreria per espressioni regolari aiuta sempre se cerchi su Google 
ne trovi tante.
Certo la sintassi del tuo file non aiuta. Immagino che sia valido anche:
<inzio
variabile
fine>
e di librerie in grado di fare il match di pattern su piu' linee non ce 
ne sono molte.
Secondo me la soluzione piu' semplice è un automa a stati finiti, ci 
sono molti modi per implementarne una in C, io da anni uso le macro:
#define FSM
#define STATE(_x)    s_##_x : if ((c = fgetc(FILEIN)) == EOF)\
                                 GOSTATE(END) ;\
                      u_##_x
#define GOSTATE(_x)  goto s_##_x
(con opportune variazioni a seconda dei casi).
Trovo che siano ottime per trasformare una FSM disegnata con carta e 
penna in un codice leggibile (assomiglia ad uno switch).
Nel tuo caso:
FSM {
     STATE(copy): if (c == '<') GOSTATE(chkvar);
                  fputc(c,out);
                  GOSTATE(copy);
     STATE(chkvar): if (c == 'i') ....
     STATE(END) : /* eventuali cleanup */
}
Naturalmente, a scanso di flame, tutto IMHO!
Remo D.
N.B. Usare macro per implementare una FSM *non* l'ho inventato  io!!
P.S. Se hai il controllo sulla sintassi del file di input, punta su 
qualcosa di piu' facilmente identificabile. Tipo: @variabile o cose del 
genere!!

     STATE(END) : /* eventuali cleanup */
Ehm, questo va in loop infinto (avrei dovuto definire la macro ENDSTATE) 
ma spero che il concetto sia chiaro ...


non è così felice, quello che devo  fare, nel concreto è sfruttare
un parser per poter dare un minimo di Server Side Include ad un server
web che non ne ha (BOA), sicuramente non è la cosa più allegra del
mondo ma non è neanche un'operazione impossibile no ?

 
Proprio non puoi fare niente per la sintassi? Un bel <@variabile> tutto 
su una riga?
Se non hai altre possibilità, come ti dicevo, una macchina a stati 
finiti e passa la paura.
Se te la disegni con carta e penna è veramente semplice. Se non ti 
piacciono le mie macro puoi usare altre tecniche (while e variabili di 
controllo a go-go) ma non dovresti avere problemi.
Tanto per darti un idea ho messo le prime transizione della FSM in forma 
tabellare ('_' rappresenta uno qualsiasi carattere spazio, '*' un 
carattere qualunque):
=== COPY
     <  *
00 10  00
=== CHECK TAG INIZIO
       i  n  i  z  i  o  _ *
10   11                10 00
11      12             11 00
12         13          12 00
13            14       13 00
14               15    14 00
15                  20 15 00
=== SKIP SPACES
      _  *
20  20 30
=== GET VARIABLE NAME
      _  *
30  40 30
=== CHECK TAG FINE
....
La leggi facilmente come:
"Nello stato 00 se arriva '<' vai nello stato 10, altrimenti resta nello 
stato 00".
"Nello stato 10 se arriva 'i' vai nello stato 11, se arriva uno spazio 
(o tab o newline etc) resta in 10 altrimenti torna nello stato 00"
e cosi' via.
Naturlmente devi organizzarti per memorizzare il nome della varibile, 
gestire le parti di testo che danno un match negativo (ad esempio 
"<init") e cosi' via.
R.
La cosa piu' bella in assoluto sarebbe creare un binding tra Boa e Lua 
(Bua??) in modo da fare tutto direttamente con uno scripting language 
invece che in C ... Ma Boa è ancora solo per Unix o hanno aggiunto il 
supporto per Windows? Ora vado a vedere ....