#include "m.h" #include #include #include /* ANSI */ int line_number = 1; #define MAXBUF 600 #define MAXLEN 128 static char buf[MAXBUF][MAXLEN]; static char *p = NULL; static int n = -1; static int savedef = -1; #define inc(n) if( ++n > MAXBUF-1) n = 0 #define dec(n) if( --n < 0) n = MAXBUF - 1 static void h_error( void) { char *q = p+1; --line_number; dec(n); p = NULL; error( "event not found: ", q); } static void recall( void) { int len, k = n; char *q; if( p[1] == '!') { dec(k); } else if( isdigit(p[1]) || p[1] == '-') { errno = 0; k = strtol( p+1, &q, 10); if( errno) { perror("strtol"); h_error(); } if( k == 0) { h_error(); } else if( k < 0) { if( abs(k) > MAXBUF-1) h_error(); k += n; if( k < 0) k += MAXBUF; } else { /* k > 0 */ if( k >= line_number || k <= line_number - MAXBUF) h_error(); k += n + 1 - line_number; if( k < 0) k += MAXBUF; } } else { /* recall by string */ len = strlen(p+1) - 1; dec(k); while( buf[k][0] && k != n) if( strncmp( buf[k], p+1, len) == 0) break; else dec(k); if( k == n) h_error(); } if( !buf[k][0]) h_error(); (void) strcpy( buf[n], buf[k]); } void history( int nlines, FILE *fout) { int start, num; if( nlines > MAXBUF) nlines = MAXBUF; start = n - nlines + 1; if( !buf[MAXBUF-1][0]) { if( start < 0) start = 0; num = n - start + 1; } else { num = n - start + 1; if( start < 0) start += MAXBUF; } while( num) { if( fout == stdout) printf( "%6d ", line_number - num); fputs( buf[start], fout); inc(start); --num; } } int m_getc( void) { if( !p || !*p) { inc(n); p = buf[n]; if( (p = fgets( p, MAXLEN, fin)) == NULL) { dec(n); return EOF; } ++line_number; loop: if( (echo && fin != stdin) || (batch && fin == stdin) ) dprint( "%s", p); else if( diary && fin == stdin && fprintf( fdiary, "m:%d> %s", line_number - 1, p) < 0) perror("fprintf"); if( *p == '$') { *(p + strlen(p) - 1) = '\0'; /* kill \n */ if( system( p+1) == -1) yyerror("system() failed"); *(p + strlen(p) - 1) = '\n'; /* put \n back */ m_gets(); if( !batch) prompt(); return m_getc(); } else if( *p == '!') { recall(); dprint( "%s", p); goto loop; } } #ifdef YYDEBUG if( yydebug) (void) printf("m_getc: returning %c\n", *p); #endif if( *p == '\\' && *(p+1) == '\n') { p += 2; return m_getc(); } return *p++; } void m_ungetc( int c) { if( --p < buf[n]) { dec(n); p = buf[n] + strlen(buf[n]) - 1; } #ifdef YYDEBUG if( yydebug) (void) printf("m_ungetc: %c\n", c); #endif *p = c; } int m_scanf( double *x) { char *q; #ifdef YYDEBUG if( yydebug) (void) printf("m_scanf: %s", p); #endif errno = 0; *x = strtod( p, &q); if( errno) perror("m_scanf"); if( errno || q == p) return 0; else { p = q; return 1; } } void m_gets( void) /* advance pointer to end of buffer */ { #ifdef YYDEBUG if( yydebug) (void) printf("m_gets: skipping %s", p); #endif p = buf[n] + strlen(buf[n]); } void fn_start( void) { savedef = n; } char *defn( void) { int i, len; char *f; if( savedef < 0) return NULL; i = savedef; len = strlen(buf[i]); while( i != n) { inc(i); len += strlen(buf[i]); } if( (f = (char *) malloc( len+1)) == NULL) { yyerror("malloc() failed in defn()"); return NULL; } i = savedef; strcpy( f, buf[i]); while( i != n) { inc(i); strcat( f, buf[i]); } return f; } void dprint( char *fmt, ...) { va_list args; va_start( args, fmt); if( vprintf( fmt, args) < 0) perror("vprintf"); if( diary) if( vfprintf( fdiary, fmt, args) < 0) perror("vfprintf"); va_end( args); } void dputchar( int c) { if( fputc( c, stdout) < 0) perror("fputc()"); if( diary && fputc( c, fdiary) < 0) perror("fputc()"); } void derror( void) { int i = -1, k = p - buf[n] - 1; dprint( "%s", buf[n]); while( ++i < k) dputchar( buf[n][i] == '\t' ? '\t' : ' '); dputchar( '^'); dputchar( '\n'); }