/* extract_subst_template: return pointer to copy of substitution template in the command buffer */ char * extract_subst_template(void) { int n = 0; int i = 0; char c; char delimiter = *ibufp++; if (*ibufp == '%' && *(ibufp + 1) == delimiter) { ibufp++; if (!rhbuf) errmsg = "no previous substitution"; return rhbuf; } while (*ibufp != delimiter) { REALLOC(rhbuf, rhbufsz, i + 2, NULL); if ((c = rhbuf[i++] = *ibufp++) == '\n' && *ibufp == '\0') { i--, ibufp--; break; } else if (c != '\\') ; else if ((rhbuf[i++] = *ibufp++) != '\n') ; else if (!isglobal) { while ((n = get_tty_line()) == 0 || (n > 0 && ibuf[n - 1] != '\n')) clearerr(stdin); if (n < 0) return NULL; } } REALLOC(rhbuf, rhbufsz, i + 1, NULL); rhbuf[rhbufi = i] = '\0'; return rhbuf; }
/* return pointer to copy of substitution template in the command buffer */ static char *extract_subst_template( const char **ibufpp, const char isglobal ) { int i = 0, n = 0; char c; const char delimiter = **ibufpp; ++(*ibufpp); if( **ibufpp == '%' && (*ibufpp)[1] == delimiter ) { ++(*ibufpp); if( !stbuf ) set_error_msg( "No previous substitution" ); return stbuf; } while( **ibufpp != delimiter ) { if( !resize_buffer( &stbuf, &stbufsz, i + 2 ) ) return 0; c = stbuf[i++] = *(*ibufpp)++; if( c == '\n' && **ibufpp == 0 ) { --i, --(*ibufpp); break; } if( c == '\\' && ( stbuf[i++] = *(*ibufpp)++ ) == '\n' && !isglobal ) { while( ( *ibufpp = get_tty_line( &n ) ) && ( n == 0 || ( n > 0 && (*ibufpp)[n-1] != '\n' ) ) ) clearerr( stdin ); if( !(*ibufpp) ) return 0; } } if( !resize_buffer( &stbuf, &stbufsz, i + 1 ) ) return 0; stbuf[stlen = i] = 0; return stbuf; }
/* exec_global: apply command list in the command buffer to the active lines in a range; return command status */ int exec_global(int interact, int gflag) { static char *ocmd = NULL; static int ocmdsz = 0; line_t *lp = NULL; int status; int n; char *cmd = NULL; if (!interact) { if (!strcmp(ibufp, "\n")) cmd = "p\n"; /* null cmd-list == `p' */ else if ((cmd = get_extended_line(&n, 0)) == NULL) return ERR; } clear_undo_stack(); while ((lp = next_active_node()) != NULL) { if ((current_addr = get_line_node_addr(lp)) < 0) return ERR; if (interact) { /* print current_addr; get a command in global syntax */ if (display_lines(current_addr, current_addr, gflag) < 0) return ERR; while ((n = get_tty_line()) > 0 && ibuf[n - 1] != '\n') clearerr(stdin); if (n < 0) return ERR; else if (n == 0) { seterrmsg("unexpected end-of-file"); return ERR; } else if (n == 1 && !strcmp(ibuf, "\n")) continue; else if (n == 2 && !strcmp(ibuf, "&\n")) { if (cmd == NULL) { seterrmsg("no previous command"); return ERR; } else cmd = ocmd; } else if ((cmd = get_extended_line(&n, 0)) == NULL) return ERR; else { REALLOC(ocmd, ocmdsz, n + 1, ERR); memcpy(ocmd, cmd, n + 1); cmd = ocmd; } } ibufp = cmd; for (; *ibufp;) if ((status = extract_addr_range()) < 0 || (status = exec_command()) < 0 || (status > 0 && (status = display_lines( current_addr, current_addr, status)) < 0)) return status; } return 0; }
/* apply command list in the command buffer to the active lines in a range; return false if error */ static bool exec_global( const char ** const ibufpp, const int gflags, const bool interactive ) { static char * buf = 0; static int bufsz = 0; const char * cmd = 0; if( !interactive ) { if( traditional() && !strcmp( *ibufpp, "\n" ) ) cmd = "p\n"; /* null cmd_list == 'p' */ else { if( !get_extended_line( ibufpp, 0, false ) ) return false; cmd = *ibufpp; } } clear_undo_stack(); while( true ) { const line_t * const lp = next_active_node(); if( !lp ) break; set_current_addr( get_line_node_addr( lp ) ); if( current_addr() < 0 ) return false; if( interactive ) { /* print current_addr; get a command in global syntax */ int len; if( !display_lines( current_addr(), current_addr(), gflags ) ) return false; do { *ibufpp = get_tty_line( &len ); } while( *ibufpp && len > 0 && (*ibufpp)[len-1] != '\n' ); if( !*ibufpp ) return false; if( len == 0 ) { set_error_msg( "Unexpected end-of-file" ); return false; } if( len == 1 && !strcmp( *ibufpp, "\n" ) ) continue; if( len == 2 && !strcmp( *ibufpp, "&\n" ) ) { if( !cmd ) { set_error_msg( "No previous command" ); return false; } } else { if( !get_extended_line( ibufpp, &len, false ) || !resize_buffer( &buf, &bufsz, len + 1 ) ) return false; memcpy( buf, *ibufpp, len + 1 ); cmd = buf; } } *ibufpp = cmd; while( **ibufpp ) if( exec_command( ibufpp, 0, true ) < 0 ) return false; } return true; }
/* put_tty_line: print text to stdout */ int put_tty_line(char *s, int l, long n, int gflag) { int col = 0; char *cp; #ifndef BACKWARDS int lc = 0; #endif if (gflag & GNP) { printf("%ld\t", n); col = 8; } for (; l--; s++) { if ((gflag & GLS) && ++col > cols) { fputs("\\\n", stdout); col = 1; #ifndef BACKWARDS if (!scripted && !isglobal && ++lc > rows) { lc = 0; fputs("Press <RETURN> to continue... ", stdout); fflush(stdout); if (get_tty_line() < 0) return ERR; } #endif } if (gflag & GLS) { if (31 < *s && *s < 127 && *s != '\\') putchar(*s); else { putchar('\\'); col++; if (*s && (cp = strchr(ESCAPES, *s)) != NULL) putchar(ESCCHARS[cp - ESCAPES]); else { putchar((((unsigned char) *s & 0300) >> 6) + '0'); putchar((((unsigned char) *s & 070) >> 3) + '0'); putchar(((unsigned char) *s & 07) + '0'); col += 2; } } } else putchar(*s); }
/* get_extended_line: get a an extended line from stdin */ char * get_extended_line(int *sizep, int nonl) { static char *cvbuf = NULL; /* buffer */ static int cvbufsz = 0; /* buffer size */ int l, n; char *t = ibufp; while (*t++ != '\n') ; if ((l = t - ibufp) < 2 || !has_trailing_escape(ibufp, ibufp + l - 1)) { *sizep = l; return ibufp; } *sizep = -1; REALLOC(cvbuf, cvbufsz, l, NULL); memcpy(cvbuf, ibufp, l); *(cvbuf + --l - 1) = '\n'; /* strip trailing esc */ if (nonl) l--; /* strip newline */ for (;;) { if ((n = get_tty_line()) < 0) return NULL; else if (n == 0 || ibuf[n - 1] != '\n') { seterrmsg("unexpected end-of-file"); return NULL; } REALLOC(cvbuf, cvbufsz, l + n, NULL); memcpy(cvbuf + l, ibuf, n); l += n; if (n < 2 || !has_trailing_escape(cvbuf, cvbuf + l - 1)) break; *(cvbuf + --l - 1) = '\n'; /* strip trailing esc */ if (nonl) l--; /* strip newline */ } REALLOC(cvbuf, cvbufsz, l + 1, NULL); cvbuf[l] = '\0'; *sizep = l; return cvbuf; }
/* Insert text from stdin (or from command buffer if global) to after line n; stop when either a single period is read or EOF. Return false if insertion fails. */ bool append_lines( const char ** const ibufpp, const int addr, const bool isglobal ) { int size = 0; undo_t * up = 0; current_addr_ = addr; while( true ) { if( !isglobal ) { *ibufpp = get_tty_line( &size ); if( !*ibufpp ) return false; if( size == 0 || (*ibufpp)[size-1] != '\n' ) { clearerr( stdin ); return ( size == 0 ); } } else { if( !**ibufpp ) return true; for( size = 0; (*ibufpp)[size++] != '\n'; ) ; } if( size == 2 && **ibufpp == '.' ) { *ibufpp += size; return true; } disable_interrupts(); if( !put_sbuf_line( *ibufpp, size, current_addr_ ) ) { enable_interrupts(); return false; } if( up ) up->tail = search_line_node( current_addr_ ); else { up = push_undo_atom( UADD, current_addr_, current_addr_ ); if( !up ) { enable_interrupts(); return false; } } *ibufpp += size; modified_ = true; enable_interrupts(); } }
int main_loop( const bool loose ) { extern jmp_buf jmp_state; const char * ibufp; /* pointer to command buffer */ volatile int err_status = 0; /* program exit status */ volatile int linenum = 0; /* script line number */ int len, status; disable_interrupts(); set_signals(); status = setjmp( jmp_state ); if( !status ) enable_interrupts(); else { status = -1; fputs( "\n?\n", stderr ); set_error_msg( "Interrupt" ); } while( true ) { fflush( stdout ); if( status < 0 && verbose ) { fprintf( stderr, "%s\n", errmsg ); fflush( stderr ); } if( prompt_on ) { printf( "%s", prompt_str ); fflush( stdout ); } ibufp = get_tty_line( &len ); if( !ibufp ) return err_status; if( !len ) { if( !modified() || scripted() ) return err_status; fputs( "?\n", stderr ); set_error_msg( "Warning: buffer modified" ); if( is_regular_file( 0 ) ) { if( verbose ) fprintf( stderr, "script, line %d: %s\n", linenum, errmsg ); return 2; } set_modified( false ); status = EMOD; continue; } else if( ibufp[len-1] != '\n' ) /* discard line */ { set_error_msg( "Unexpected end-of-file" ); status = ERR; continue; } else ++linenum; status = exec_command( &ibufp, status, false ); if( status == 0 ) continue; if( status == QUIT ) return err_status; if( status == EMOD ) { fputs( "?\n", stderr ); /* give warning */ set_error_msg( "Warning: buffer modified" ); if( is_regular_file( 0 ) ) { if( verbose ) fprintf( stderr, "script, line %d: %s\n", linenum, errmsg ); return 1; } } else if( status == FATAL ) { if( verbose ) { if( is_regular_file( 0 ) ) fprintf( stderr, "script, line %d: %s\n", linenum, errmsg ); else fprintf( stderr, "%s\n", errmsg ); } return 1; } else { fputs( "?\n", stderr ); /* give warning */ if( is_regular_file( 0 ) ) { if( verbose ) fprintf( stderr, "script, line %d: %s\n", linenum, errmsg ); return 1; } } if( !loose ) err_status = 1; } }