home *** CD-ROM | disk | FTP | other *** search
- /* Very Intelligent filter */
- /* © 1990 Pagani Massimiliano */
-
- /* Per compilare col Lattice C: */
- /* lc -L -cfist -d0 vif.c */
-
- /* Questo filtro dovrebbe fare le seguenti cose: */
- /* - Rimuovere i caratteri vuoti (spazi, tab) alla fine delle linee */
- /* - Sostituire spazi consecutivi con caratteri tab rispettando le di- */
- /* mensioni */
- /* - Rimuovere gli spazi coperti da un tab. */
- /* - Rimuovere i newline alla fine del file. */
- /* - i ^Z, ^M */
- /* opzionalmente: */
- /* - rimuovere le sequenze di escape. */
-
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <error.h>
- #include <ctype.h>
- #include <dos.h>
- #include <fcntl.h>
-
- /* Stato dell'automa */
- typedef enum {RESET, SPAZIO, TAB, NEWLINE} STATO;
-
- #ifdef LATTICE
- /* Gli errori vengono trovati controllando la errno */
- /* prototipi */
- void ShowHelp(void);
- BOOL copyfile( unsigned char *, unsigned char * );
- BOOL OutChars( int, unsigned char, FILE * );
- void ExaustEscape( unsigned char, FILE *, FILE * );
- STATO DoSpazio( STATO, int *, int *, int * );
- void DoTab( STATO, int *, int *, int * );
- void DoNewLines( STATO, int *, int *, int *, int * );
- void DoFilter( FILE *, FILE *, BOOL, BOOL, BOOL );
- int main( int, char ** );
- #else
- # define FALSE 0L
- # define TRUE (!FALSE)
- typedef int BOOL;
- #endif
-
- #undef DEBUG
-
-
- #define TABSIZE 8
- #define ISTAB(col) (!(((col)-1)-TABSIZE*(((col)-1)/TABSIZE)))
- /* è una macro che ritorna TRUE quando la colonna attuale è */
- /* una tabulazione, FALSE altrimenti */
- #define NEXTTAB(col) ((col)+TABSIZE-(((col)-1)%TABSIZE))
- /* ritorna la prossima possizione di tabulazione */
-
- /* Variabili importate */
- extern int errno;
-
-
- void
- ShowHelp()
- {
- puts("converts spaces into tabs,");
- puts("removes useless spaces, tabs, control chars and");
- puts(" escape sequences");
- puts("Usage:");
- puts(" vif [s] [<file> | (<filein> <fileout>)]");
- puts("[s] any combination of switches precedeed by '-':");
- puts(" e do not strip escape sequences.");
- puts(" q no statistic at the end.");
- puts(" p progressing display.");
- puts("If no files specified stdin and stdout will be used.");
- puts("If only one file, the filtering will be done on a");
- puts("temporary file (in T:) then the result will be copied");
- puts("onto the original file (WARNING).");
- puts("If two files specified filtering will be applied on");
- puts("<filein> and result in <fileout>.");
- }
-
- BOOL
- copyfile( name_in, name_out )
- unsigned char * name_in;
- unsigned char * name_out;
- {
- int fd_in, fd_out;
- char buffer[ BUFSIZ ];
- int count = -1L;
-
- fd_in = open( name_in, O_RDONLY );
- fd_out = open( name_out, O_CREAT | O_WRONLY | O_TRUNC, 0 );
- if( fd_in && fd_out ){
- while( (count = read( fd_in, buffer, BUFSIZ )) > 0){
- if( write( fd_out, buffer, count ) != count ){
- printf("problema in scrittura\n");
- break;
- }
- }
- close( fd_in );
- close( fd_out );
- }
- # ifdef DEBUG
- printf("errno = %d\n", errno );
- # endif
- return( (BOOL) errno );
- }
-
- BOOL
- OutChars( n, c, out )
- int n;
- unsigned char c;
- FILE *out;
- {
-
- #ifdef DEBUG
- printf("scrivo %d ", n );
- switch( c ){
- case ' ':
- printf("spazi\n");
- break;
- case '\n':
- printf("nl\n");
- break;
- case '\t':
- printf("tab\n");
- break;
- }
- #endif
-
- for( ; n > 0; n-- ){
- putc( c, out );
- }
- return( (BOOL) !errno ); /* (errno == 0) -> ok */
- }
-
- /* Esaurisce la sequenza di escape */
-
- void
- ExaustEscape( c, in, out )
- unsigned char c;
- FILE *in;
- FILE *out;
- {
- enum { ESC1B, ESC9B, NUMERO, FINE } stato;
-
- if( c == 0x1B ) stato = ESC1B;
- else stato = ESC9B;
- while( stato != FINE ){
- c = getc( in );
- if( out ) putc( c, out );
- switch( stato ){
- case ESC1B:
- switch( c ){
- case '[':
- stato = ESC9B;
- break;
- default:
- stato = FINE;
- }
- break;
- case ESC9B:
- if( isdigit( c ) || (c==';') ){
- stato = NUMERO;
- }
- else stato = FINE;
- break;
- case NUMERO:
- if( !isdigit( c ) && (c != ';') ){
- stato = FINE;
- }
- break;
- }
- }
- }
-
- /* risolve il problema quando il carattere letto è uno spazio */
-
- STATO
- DoSpazio( stato, col, numSpazi, numTab )
- STATO stato;
- int *col, *numSpazi, *numTab;
- {
-
- (*col)++;
- switch( stato ){
- case RESET:
- case SPAZIO:
- *numSpazi = (stato == RESET) ? 1 : *numSpazi+1;
- if( ISTAB( *col ) ){
- *numSpazi = 0;
- (*numTab)++;
- stato = TAB;
- }
- else stato = SPAZIO;
- break;
- case TAB:
- /* ci sono dei tab, quindi uno spazio */
- (*numSpazi)++;
- stato = SPAZIO;
- break;
- case NEWLINE:
- *numSpazi = 1;
- stato = SPAZIO;
- break;
- }
- return( stato );
- }
-
- /* risolve il problema quando il carattere letto è un tab */
-
- void
- DoTab( stato, col, numSpazi, numTab )
- STATO stato;
- int *col;
- int *numSpazi, *numTab;
- {
-
- *col = NEXTTAB( *col );
- switch( stato ){
- case NEWLINE:
- case RESET:
- *numTab = 1;
- break;
- case SPAZIO:
- /* un certo numero di spazi, quindi un tab */
- /* al massimo una tabulazione, quindi il tab copre gli spazi */
- (*numTab)++;
- *numSpazi = 0;
- break;
- case TAB:
- (*numTab)++;
- break;
- }
- }
-
- void
- DoNewLines( stato, col, numSpazi, numTab, numNewLine )
- STATO stato;
- int *col;
- int *numSpazi, *numTab, *numNewLine;
- {
-
- *col = 1;
- switch( stato ){
- case RESET:
- *numNewLine = 1;
- break;
- case SPAZIO:
- case TAB:
- /* abbiamo dei vuoti seguiti da un newLine */
- *numTab = *numSpazi = 0;
- case NEWLINE:
- (*numNewLine)++;
- break;
- }
- }
-
- void
- DoFilter( in, out, noStat, stripESC, progress )
- FILE *in, *out;
- BOOL noStat, stripESC; /* flags */
- BOOL progress;
- {
- STATO stato; /* stato dell'automa */
- int c; /* ultimo carattere letto */
- int char_in = 0L; /* # di caratteri letto */
- int char_out = 0L; /* # caratteri scritti */
- BOOL lineaVuota; /* la linea che stiamo leggendo è vuota ? */
- int numSpazi, numTab, numNewLine;
- /* # spazi, tab e nl consecutivi */
- int col; /* colonna attuale */
- register int linea; /* # di linea attuale */
- char count = 0; /* contatore simbolini */
- register int tlinea=0;
-
- #ifdef DEBUG
- printf("DoFilter: inizio\n");
- #endif
-
- col = linea = 1L;
- numSpazi = numTab = numNewLine = 0L;
- lineaVuota = TRUE;
- stato = RESET;
- do {
- c = getc( in );
- char_in++;
-
- #ifdef DEBUG
- printf("%d %d -> letto %2x", col, linea, c );
- if( c > 32 ) printf("\t%c", c );
- putchar( '\n' );
- #endif
- if( progress && ((linea>>4) != tlinea) ){
- tlinea = linea>>4;
- putchar( '#' );
- if( ++count > 40 ){
- count = 0;
- putchar( '\n' );
- }
- fflush( stdout );
- }
- switch( c ){
- case ' ':
- stato = DoSpazio( stato, &col, &numSpazi, &numTab );
- break;
- case '\t':
- DoTab( stato, &col, &numSpazi, &numTab );
- stato = TAB;
- break;
- case '\n':
- DoNewLines( stato, &col, &numSpazi, &numTab, &numNewLine );
- stato = NEWLINE;
- linea++;
- lineaVuota = TRUE;
- break;
- case 0xD:
- case 0x1A:
- /* ignoriamo i CR e gli EOF dei baracchi */
- break;
- case 0xC: /* Form Feed */
- putc( c, out );
- char_out++;
- col = 1;
- lineaVuota = TRUE;
- break;
- case 0x1B: /* Escape sequence */
- case 0x9B:
- ExaustEscape( (unsigned char) c, in, (stripESC ? NULL : out) );
- break;
- case EOF:
- break;
- default:
- lineaVuota = FALSE;
- col++;
- char_out++;
- if( numNewLine > 0 ){
- OutChars( numNewLine, '\n', out );
- char_out += numNewLine;
- numNewLine = 0L;
- }
- if( numTab > 0 ){
- OutChars( numTab, '\t', out );
- char_out += numTab;
- numTab = 0L;
- }
- if( numSpazi > 0 ){
- OutChars( numSpazi, ' ', out );
- char_out += numSpazi;
- numSpazi = 0L;
- }
- putc( c, out );
- stato = RESET;
- break;
- }
- } while( (c != EOF) && (errno==0) );
- if( errno ){
- perror("vif");
- }
- else {
- if( progress ) putchar( '\n' );
- if( !noStat ){
- printf("processate %ld linee\n", linea );
- printf("letti %ld caratteri\n", --char_in );
- printf("scritti %ld caratteri\n", char_out );
- if( char_out > 0 ){
- printf("Compressed %ld%%\n", 100*(char_in - char_out)/char_out );
- }
- }
- }
- }
-
- int
- main( argc, argv )
- int argc;
- char **argv;
- {
- int ind;
- char *copt; /* puntatore opzione corrente */
- FILE *in;
- FILE *out;
- BOOL oneFile = FALSE; /* lavora su un file temporaneo */
- BOOL noStat = FALSE; /* nessuna statistica alla fine */
- BOOL stripESC = TRUE; /* toglie gli escape */
- unsigned char tmpname[ FMSIZE ]; /* nome file temporaneo */
- int count; /* # del file in area temporanea */
- BOOL done = FALSE; /* Finito */
- BOOL progress = FALSE; /* indica il progredire */
-
- printf("VIF: very intelligent filter\n");
- printf(" © 1990 Pagani Massimiliano\n");
- printf(" ShareWare - see doc file\n");
- printf("----------------------------\n");
- if( (argc == 2) && (*argv[1] == '?') ){
- ShowHelp();
- exit( 0L );
- }
- if( (argc > 1) && (*argv[1] == '-')){
- /* sono state specificate delle opzioni */
- for( copt=argv[1]+1; *copt; copt++ ){
- switch( *copt ){
- case 'e': /* conserviamo le seq. di escape */
- stripESC = FALSE;
- break;
- case 'q': /* quiet */
- noStat = TRUE;
- break;
- case 'p': /* indica il progredire */
- progress = TRUE;
- break;
- default:
- printf("Ignoro -%c in quanto non valido. \n", *copt );
- }
- }
- ind = 2;
- }
- else {
- ind = 1;
- }
- if( ind == argc ){
- progress = FALSE; /* altrimenti rompiamo le scatole */
- noStat = TRUE; /* idem con patate */
- in = stdin;
- out = stdout;
- # ifdef DEBUG
- printf("Applico il filtro sullo stdin, output su stdout\n");
- # endif
- }
- else if( (ind+1) == argc ){
- # ifdef DEBUG
- printf("Applico il filtro su %s out in temp\n", argv[ind]);
- # endif
- /* c'è un solo file */
- oneFile = TRUE;
- in = fopen( argv[ind], "r" );
- for( count=0; !done; count++ ){
- sprintf( tmpname, "T:viftemp%d", count );
- if( access( tmpname, 0 ) == -1 ){
- /* Un errore o semplicemente non c'è */
- if( errno != ENOENT ){
- out = NULL;
- perror( tmpname );
- }
- else {
- out = fopen( tmpname, "w" );
- errno = 0L;
- }
- done = TRUE;
- }
- }
- }
- else {
- in = fopen( argv[ind], "r" );
- out = fopen( argv[ind+1], "w" );
- #ifdef DEBUG
- printf("Applico il filtro sul file \"%s\" output su \"%s\"\n", argv[1], argv[ind+1] );
- #endif
- }
- if( !in ){
- fprintf( stderr, "non riesco ad aprire il file %s in lettura\n", argv[ind] );
- exit( 10L );
- }
- if( !out ){
- fprintf( stderr, "non riesco ad aprire il file %s in scrittura\n", argv[ind+1] );
- exit( 11L );
- }
- DoFilter( in, out, noStat, stripESC, progress );
- if( oneFile && (errno==0) ){
- fclose( in );
- fclose( out );
- if( !copyfile( tmpname, argv[ ind ]) ){
- remove( tmpname );
- }
- else {
- puts("problemi nel copiare il file temporaneo");
- puts("recupera il contenuto del file in:");
- puts( tmpname );
- }
- }
-
- return( errno );
- }
-