home *** CD-ROM | disk | FTP | other *** search
- /* **************************************************************
-
- Programma ...... Calc.c
- Versione ....... 2.01, 1 Maggio 1990
- Scopo .......... Calcolo di espressioni ASCII con numeri f.p.
- Autore ......... Luigi Callegari
- Sintassi ....... Calc [expr] || Calc [nomefile]
- Hardware ....... Amiga standard 500/2500, Kickstart V1.2/1.3/1.4
- Software ....... Lattice C V5.04, Aztec C V5.0a
- Make Lattice ... LC -cusf -vbr -Lntvm -O -fi Calc
- Make Aztec ..... CC -fa -sb -so Calc, LN calc -lma -lc
-
- ************************************************************** */
-
- #define MAXOPL 5 /* Massimo numero di livelli */
- #define MAXELE 50 /* Massimo numero di operandi aritmetici */
- #define NOP 0 /* Token di "nessuna operazione" */
- #define ADD 1 /* Token di somma aritmetica */
- #define SUB 2 /* Token di sottrazione aritmetica */
- #define MUL 3 /* Token di moltiplicazione aritmetica */
- #define DIV 4 /* Token di divisione aritmetica */
- #define POW 5 /* Token di elevazione a potenza */
- #define PRIOR POW /* Operazione prioritaria per importanza */
-
- #define isoper(c) (c=='+'||c=='-'||c=='/'||c=='*'||c=='^')
-
- #include <string.h> /* Funzioni di gestione stringa */
- #include <stdlib.h> /* Funzioni di libreria standard */
- #include <ctype.h> /* Funzioni isxxxx() */
- #include <stdio.h> /* I/O Standard */
- #include <math.h> /* Matematica */
- #include <libraries/dos.h> /* Gestione AmigaDOS */
-
- #ifdef LATTICE
- # include <proto/all.h>
- #else
- # include <functions.h>
- #endif
-
- double num[ MAXELE ]; /* Matrice Operandi */
- int op[ MAXELE ][ MAXOPL ]; /* Matrice Operatori aritmetici */
- int lev; /* Livello operatori */
- int nop; /* Numero effettivo operatori */
- int nel; /* Numero effettivo operandi */
- char *buf; /* Buffer per elaborazione batch */
- BPTR lucc; /* Lock di file */
-
- /* ******** Uscita da errore con messaggio di postmortem ****** */
-
- void die( char *s ) /* Puntatore a messaggio di errore */
- {
- if ( lucc ) UnLock( lucc );
- fprintf( stderr, "\n%s\n", s );
- exit( 10L );
- }
-
- /* Ritorna lunghezza in caratteri di una stringa ASCII rappresentante
- un numero in virgola mobile, con eventuale notazione esponenziale */
-
- int luncifra( char *s )
- {
- int j = 0;
-
- while ( isdigit( s[ j ] ) ) ++j; /* Salta parte intera */
- if ( s[ j ] == '.' )
- {
- ++j;
- while ( isdigit( s[ j ] ) ) ++j; /* Salta eventuali decimali */
- }
-
- if ( s[ j ] == 'e' || s[ j ] == 'E' )
- {
- ++j; /* Salta parte esponenziale */
- if ( s[ j ] == '+' || s[ j ] == '-' )
- ++j;
- while( isdigit( s[ j ] ) ) ++j;
- }
-
- return( j );
- }
-
- /* ************ Corregge matrici dopo una operazione ********** */
-
- void compr( int *k ) /* Puntatore a posizione di operando usato */
- {
- unsigned short int j, i; /* Variabili di lavoro */
-
- --nop; --nel; /* Aggiusta contatori di operatori e operandi */
-
- for ( j=*k ; j<nel ; j++ ) /* Elimina operando usato */
- num[ j+1 ] = num[ j+2 ];
-
- for ( i=0 ; i<MAXOPL ; i++ ) /* Elimina operatore usato */
- for ( j=*k ; j<nop ; j++ )
- op[ j ][ i ] = op[ j+1 ][ i ];
-
- *k -= 1; /* Riporta puntatore scansione a posizione corretta */
- return;
- }
-
- /*************** Memorizza operandi ed operatori ***************/
-
- void parse( char *s ) /* Stringa ASCII dell'espressione */
- {
- int c; /* Carattere da esaminare */
- int j; /* Variabili di lavoro */
- short operation; /* Operazione da eseguire */
-
- for ( j=0 ; j<strlen(s) ; j++ ) {
- c = s[ j ];
-
- if ( c == ')' && --lev < 0 )
- die( "Troppe parentesi chiuse!" );
-
- else if ( c == '(' && ++lev == MAXOPL )
- die( "Troppe parentesi aperte!" );
-
- else if ( isoper( c ) ) { /* Memorizza operatore */
- switch( c ) {
- case '^' : operation = POW; break;
- case '+' : operation = ADD; break;
- case '-' : operation = SUB; break;
- case '*' : operation = MUL; break;
- case '/' : operation = DIV; break;
- default : operation = NOP; break;
- } /* end switch(c) */
- op[ nop++ ][ lev ] = operation;
- } /* end else if() */
-
- else if ( isdigit( c ) ) { /* Memorizza operando */
- num[ nel++ ] = (double) atof( &s[ j ] );
- if ( nel >= MAXELE )
- die( "Troppi operandi!" );
-
- j += luncifra( &s[ j ] ) - 1; /* Salta numero inserito */
- } /* end else if */
- } /* end for (j) */
- return;
- } /* end parse() */
-
- /************ Esegue materialmente i calcoli ***************/
-
- double calc( char *s ) /* Puntatore a stringa di espressione */
- {
- int j, i;
-
- (void)parse( s ); /* Crea matrici operandi e operatori */
-
- for ( lev=MAXOPL-1 ; lev>=0 ; lev-- ) /* Da livello massimo */
- {
- for ( j=PRIOR ; j >= ADD ; j-- ) /* Da oper. prioritaria */
- for ( i=0 ; i < nop; i++ ) /* Da primo operatore */
- if ( op[ i ][ lev ] == j )
- {
- switch( op[ i ][ lev ] ) {
- case DIV: num[ i ] /= num[ i+1 ]; break;
- case MUL: num[ i ] *= num[ i+1 ]; break;
- case ADD: num[ i ] += num[ i+1 ]; break;
- case SUB: num[ i ] -= num[ i+1 ]; break;
- case POW: num[ i ] = pow(num[i],num[i+1]);break;
- default : break;
- } /* end switch */
-
- compr( &i ); /* Aggiorna matrici */
- } /* end if */
- } /* end for (lev) */
- return( num[ 0 ] );
- }
-
- /* ********** Funzione trasferimento file in buffer ************ */
- char *makebuf( char *s )
- {
- struct FileInfoBlock *fib;
- char *ptr;
- LONG lunfile;
- BPTR fileh;
-
- if (!(lucc=Lock(s, ACCESS_READ) ) )
- die("Locking impossibile!");
-
- if (!(fib=(struct FileInfoBlock*)malloc(sizeof(struct FileInfoBlock))))
- die( "Manca memoria per FIB" );
-
- if ( ! Examine( lucc, (BPTR) fib ) )
- die( "Non esamino file!" );
-
- lunfile = fib -> fib_Size; UnLock( lucc );
- lucc = (BPTR) NULL;
-
- if ( ! (ptr = (char *) malloc( lunfile ) ) )
- die("Manca memoria");
-
- if ( ! (fileh=Open( s, MODE_OLDFILE )))
- die("Non si apre il file");
-
- if ( Read( fileh, ptr, lunfile ) != lunfile)
- die("Errore di I/O");
-
- Close( fileh );
-
- return( ptr );
- }
-
- /************ Funzione principale *****************/
-
- void main( int argc, char *argv[] )
- {
- if ( argc != 2 ) { /* Sintassi errata */
- printf( "\nSintassi: %s [expr|nomefile]\n", argv[ 0 ] );
- exit( 10L );
- }
-
- if ( isalpha( argv[1][0] )) /* Dato un nome di file */
- printf("File %s = %.8g\n", argv[1], calc(makebuf(argv[1])));
-
- else /* Data un'espressione */
- printf( "%s = %.8g\n", argv[ 1 ], calc( argv[ 1 ] ) );
-
- exit( 0L );
- }
-