Newsgroup: it.comp.lang.c
Titolo: rimuovere i commenti

Sperando di non essere troppo OT,
avrei l'esigienza di fare pulizia in molti sorgenti scritti in C,
e vorrei eliminare tutti i commenti (la documentazione l'ho prodotta in modo
differente su
appositi file e anche in diagrammi UML) per poi riscriverne meglio solo gli
essenziali.
Esiste un qualche tool che in automatico scorre il sorgente ed elmina tutto
quello che trova alla destra di "//"
e tra "/*" e  "*/"  ?
Grazie
Marco

 e tra "/*" e  "*/"  ?
Non che io sappia, ma e' facile farsene uno in C, o addirittura banale in
Perl (se hai un interprete perl).
Tommy


si č vero... volendo ho un server su cui gira il php quindi potrei farmi uno
script, ma era per non perdere tempo perchč
sono veramente oberato in questo momento...
Ciao

 Tommy
Già, sebbene trattare il caso in cui i caratteri di inizio e fine commento
sono parti di una stringa (e quindi non indicanti effettivamente un commento
e da NON rimuovere) non sia del tutto banale (almeno in C, dato che il Perl
non lo conosco)...
Sergio

 wrote in message
news:DZBR9.55175$Q%4.18...@news1.tin.it...


Con le espressioni regolari in Perl lo e' .
In C non ho mai detto che sia banale. Ho detto facile. Forse non e' la
parola adatta, ma di sicuro non e' difficilissimo :-).
Inoltre bisogna vedere se per il programma specifico questo sia importante o
meno.
Tommy

Ti ripeto che non conosco il Perl (sebbene dovrò "affrontarlo" molto presto
per motivi di studio) ma conosco abbastanza bene il C e posso dirti, con
tutta la modestia del mio parere, che trattare il caso prima citato
(ovviamente in modo efficiente)  non mi sembra nè banale nè facile.
Certo non è difficilissimo, ma da qui a dire "facile" c'è un bel po' di
strada.
Saluti,
Sergio

 wrote

http://www.bdc.cx/software/stripcmt/
questo sito presenta un programma scritto in C per fare quello che il post
originariamente chiedeva.
Ovviamente questo prog. e' piu' complesso e funziona per piu' linguaggi e da
linea di comando e non.
Per essere onesto non mi sembra fatto benissimo, e potrebbe non essere il
massimo della efficienza e sicurezza ma se guardi la funzione che fa tale
compito e semplice, non banale, ma semplice.
Non l'ho testato, ma e' tutta qua:
<CODE>
void
stripcmt (FILE *infile, FILE *outfile)
{
  char buffer [BUFSIZ];
  char quote = 0, comment = 0;
  int  i;
  while (fgets(buffer, sizeof buffer, infile))
  {
      for (i = 0; buffer[i]; i++)
      {
          switch (buffer[i])
          {
              /* Take care of control characters starting with '\' */
              case '\\':
                  if (comment)    /* If we're in a comment, don't bother */
                      break;
                  fputc(buffer[i], outfile);
                  fputc(buffer[++i], outfile);
                  break;
              /* Handle either type of quotes (' or "). */
              case '\"':
              case '\'':
                  if (comment)
                      break;
                  fputc(buffer[i], outfile);
                  if (!quote)
                      quote = buffer[i];
                  else if (quote == buffer[i])
                      quote = 0;
                  break;
              /* This handles both C++ comments and opening C comments */
              case '/':
                  if (quote)
                       fputc(buffer[i], outfile);
                  else if (buffer[i+1] == '/')
                  {
                      fputc('\n', outfile);
                      memset(buffer, 0, sizeof buffer);
                  }
                  else if (buffer[i+1] == '*')
                  {
                      comment = 1;
                      i++;
                  }
                  else if (!comment)
                      fputc(buffer[i], outfile);
                  break;
              /* This handles closing C style comments */
              case '*':
                  if (quote)
    {
                       fputc(buffer[i], outfile);
         break;
    }
                  else if (comment && buffer[i+1] == '/')
                  {
                      comment = 0;
                      i++;
                      break;
                  }
                  else if (comment)
                      break;
                  fputc(buffer[i], outfile);
                  break;
              /* Anything else?  Show it if necessary. */
              default:
                  if (!comment)
                      fputc(buffer[i], outfile);
                  break;
          }  /* End of switch */
      }  /* End of for() */
  }  /* End of while() */
  return;
}
</CODE>
Tommy

 wrote

Allora ho messo sul mio compilatore SOLO la funzione che ho postato....
e ci ho aggiunto un breve main:
<CODE>
int main()
{
    FILE *fin;
    FILE *fout;
    fin=fopen("x.txt","r");
    fout=fopen("x2.txt","w");
    stripcmt (fin,fout);
    fclose(fout);
    fclose(fin);
    return 0;
}
</CODE>
Ho creato il file x.txt:
<TXT>
#include<stdio.h>
/*
 COMMENTO MULTILINE
*/
// Commento single line!
int main()     /* Questa e' la funzione principale */
{
     printf("/*non e' un commento*/ NO!\n");
     printf("questo // nemmeno!\n");     // QUESTO SI PERO'!
     printf("questo /* ancora // di meno\n");
     return 0;
}
</TXT>
Come vedi prova alcuni casi..... Ecco il risultato x2.txt
<TXT>
#include<stdio.h>
int main()
{
     printf("/*non e' un commento*/ NO!\n");
     printf("questo // nemmeno!\n");
     printf("questo /* ancora // di meno\n");
     return 0;
}
</TXT>
Come vedi ha funzionato ed il codice non e' cosi' difficile.
Non garantisco il sofware qui presente funzioni bene in tutti i casi, non
l'ho testato a fondo.
In perl con le regex penso si riesca a scrivere in 10 righe!
Tommy

Ho dato un'occhiata alla funzione, non sembra il massimo dell'efficienza e
soprattutto della chiarezza, che è un mio "pallino".
Tuttavia, da tuo esperimento, sembra che funzioni.
Rimango in ogni caso della stessa idea.
Sarà perchè, data la mia esperienza, evito sempre di definire "facile" la
risoluzione di un qualsiasi problema, persino di "Hello World".
Soprattutto quando il problema non l'ho nè affrontato nè risolto.
A risentirci,
Sergio

 e tra "/*" e  "*/"  ?
se fai andare il solo preprocessore, mettendo gli #include tra /**/, hai 
quel che cerchi

 (ovviamente in modo efficiente)  non mi sembra nè banale nè facile.
Ecco una soluzione efficiente in PERL, l'algoritmo sta in una sola riga:
$all =~
s#/\*[^*]*\*+([^/*][^*]*\*+)*/|//[^\n]*|("(\\.|[^"\\])*"|'(\\.|[^'\\])*'|.[^
/"'\\]*)#$2#gs;
(Se il server delle news la spezza, e' solo una riga.)
Questa linea presume che $all sia una variabile che contiene TUTTO il file.
Se vuoi, per email ti posto il codice completo di 5 righe con possibilita'
di decidere at run time il file di input e quello di output, aprire il
primo, leggerlo, eseguire l'espressione regolare sopra riportata ed infine
scrivere il secondo file.
Non lo posto qua in quanto sarebbe OT.
Questo funziona bene e come ti ho detto fare questo programma in C e'
semplice, in PERL e' piu' semplice e si scrive in una riga. (banale era un
tantino forte in effetti).
Tommy


Interessante.
Quando affronterò il Perl magari ne riparleremo.
Per adesso ti credo sulla parola.
:-)
Ciao e a presto,
Sergio