home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
613b.lha
/
VIF
/
vif.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-10-11
|
11KB
|
481 lines
/* 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 );
}