Back to index

texmacs  1.0.7.15
tm_r.c
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : tm_r.c
00004 * DESCRIPTION: Glue between TeXmacs and R
00005 * COPYRIGHT  : (C) 2003 Michael Lachmann Tamarlin
00006 *******************************************************************************
00007 * This software falls under the GNU general public license version 3 or later.
00008 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00009 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00010 ******************************************************************************/
00011 
00012 #include <stdio.h>
00013 #include <sys/select.h>
00014 #if HAVE_PTY_H
00015 #include <pty.h>
00016 #endif
00017 
00018 #include <utmp.h>
00019 #include <unistd.h>
00020 #include <termios.h>
00021 #include <stdlib.h>
00022 #include <signal.h>
00023 #include <string.h>
00024 #include <util.h>
00025 
00026 #include <sys/types.h>
00027 #include <sys/stat.h>
00028 #include <fcntl.h>
00029 #include <sys/time.h>
00030 #include <sys/types.h>
00031 #include <unistd.h>
00032 #include <errno.h>
00033 
00034 /* do we want to talk with texmacs, or with a human? */
00035 #define INTERFACE_TEXMACS
00036 #define USE_DEBUG
00037 
00038 #ifdef INTERFACE_TEXMACS
00039 #define DATA_BEGIN (2)
00040 #define DATA_END (5)
00041 #define DATA_COMMAND (16)
00042 #else
00043 #define DATA_BEGIN '{'
00044 #define DATA_END '}'
00045 #define DATA_COMMAND '@'
00046 #endif
00047 
00048 #define IN_VERBATIM( TXB ) { if( in_data == 0 ) { in_data=1 ; copy_to_B( TXB, st, snprintf(st,4096,"%cverbatim:",DATA_BEGIN) ) ; } }
00049 #define END_VERBATIM( TXB ) { while( in_data>0 ) { copy_to_B( TXB, st, snprintf(st,4096,"%c",DATA_END) ) ; in_data-- ;}}
00050 #define B_DATA_BEGIN( TXB ) { copy_to_B( TXB, st, snprintf(st,4096,"%c",DATA_BEGIN) ); in_data++; }
00051 #define B_DATA_END( TXB ) { copy_to_B( TXB, st, snprintf(st,4096,"%c",DATA_END) ); in_data--; }
00052 
00053 
00054 #ifndef USE_DEBUG
00055 #define WRITELOG(s,n)
00056 int DEBUG = (1==0) ;
00057 
00058 /* #define VERBOSE_TERM */
00059 #undef VERBOSE_TERM
00060 #else
00061 #define WRITELOG(s,n) {if( DEBUG ) write(LOG,s,n);}
00062 int LOG ;
00063 int DEBUG = (1==1) ;
00064 #endif
00065 
00066 char st[4096] ;
00067 
00068 char *temp_buf;
00069 
00070 tcflag_t prompt_flags[][4] = {
00071 { 00500,  000005, 0277,      0005021},
00072 {00000,  000005, 0277,      0105061},
00073 {00000,  000004, 0277,      0005061},
00074 {02400,  014005, 0277,      0105001},
00075 {0,          05, 0277, 037777763425},
00076 {-1,-1,-1,-1}
00077 } ;
00078 
00079 
00080 
00081 int check_terminal( int f )
00082 {
00083   int p_i ;
00084   int got_prompt = (1==0) ;
00085   struct termios termi ;
00086   tcgetattr(f, &termi ) ;
00087   WRITELOG(st,snprintf(st,4096,"term:i:%o o:%o c:%o l:%o\n",
00088                      (unsigned int) termi.c_iflag,
00089                      (unsigned int) termi.c_oflag,
00090                      (unsigned int) termi.c_cflag,
00091                      (unsigned int) termi.c_lflag)) ;
00092   
00093   /* check if we got the prompt from R */
00094   for( p_i = 0; prompt_flags[p_i][0]!=-1; p_i++) {  /* check terminal flags */
00095     WRITELOG(st,snprintf(st,4096,"p_i = %d %d\n", p_i,
00096                       (int) prompt_flags[p_i][0])) ;    
00097     WRITELOG(st,snprintf(st,4096,"prompt:i:%o o:%o c:%o l:%o\n",
00098                       (unsigned int) prompt_flags[p_i][0],
00099                       (unsigned int) prompt_flags[p_i][1],
00100                       (unsigned int) prompt_flags[p_i][2],
00101                       (unsigned int) prompt_flags[p_i][3])) ;      
00102     if( (termi.c_iflag == prompt_flags[p_i][0]) &&
00103           (termi.c_oflag == prompt_flags[p_i][1]) &&
00104           (termi.c_cflag == prompt_flags[p_i][2]) &&
00105           (termi.c_lflag = prompt_flags[p_i][3]) ) {
00106          got_prompt = (1==1) ;
00107          WRITELOG(st,snprintf(st,4096,"found prompt 1\n"))      
00108          break ; 
00109        } else {
00110          WRITELOG(st,snprintf(st,4096,"no prompt 1\n"))               
00111        }
00112   }
00113   WRITELOG(st,snprintf(st,4096,"p_i = %d %d\n", p_i,
00114                      (int) prompt_flags[p_i][0])) ;     
00115   return got_prompt ;
00116 }
00117 
00118 
00119 char *prompt_string[] = {
00120 "> ",
00121 "; ",
00122 "+ ",
00123 "$ ",
00124 ":",
00125 "# ",
00126 "(B",
00127 "Type  <Return>\t to start : ",
00128 "Save workspace image? [y/n/c]: ",
00129 "Hit <Return> to see next plot: ",
00130 "Password: ",
00131 0
00132 } ;
00133 
00134 struct my_buffer {
00135   char *buf ;
00136   int size, get, put ;
00137 } ;
00138 
00139 
00140 int compare_end_B( struct my_buffer *b, char *string )
00141 {
00142   int n,ret;
00143   
00144   n = strlen( string ) ;
00145   if( n > b->put - b->get )
00146     return (1==0) ;
00147   
00148   ret = strncmp( b->buf+b->put-n, string,n ) ;
00149   return( ret==0 ) ;
00150 }
00151 
00152 int check_prompt_strings_B( struct my_buffer *B )
00153 {
00154   int p_i ;
00155   int got_prompt = (1==0) ;
00156   for( p_i=0; prompt_string[p_i]!=0; p_i++)
00157     if( compare_end_B( B, prompt_string[p_i] ) ) {
00158       WRITELOG(st,snprintf(st,4096,"Found string:%s\n",prompt_string[p_i]) ) ;
00159       got_prompt=(1==1) ;
00160       break ;
00161     }
00162   return got_prompt ;
00163 }  
00164 
00165 int tab_comp_ptr=0;
00166 
00167 char big[1000] ;
00168 
00169 pid_t childpid ;
00170 
00171 int not_done=(1==1) ;
00172 
00173 int master ;
00174 
00175 void child_died(int x) ;
00176 void something_wrong(int x) ;
00177 
00178 void signal_int(int x)
00179 {
00180   char st[4096];
00181   WRITELOG(st,snprintf(st,4096,"got signal %d\n",childpid) ) ;
00182   write(master,"",1) ;
00183 //  kill(childpid,SIGINT) ;
00184   signal (SIGINT, signal_int);
00185   signal (SIGCHLD, child_died);
00186   signal (SIGBUS, something_wrong ) ;
00187   signal (SIGABRT, something_wrong ) ;
00188   signal (SIGILL, something_wrong ) ;
00189   signal (SIGSEGV, something_wrong ) ;
00190 
00191 }
00192 
00193 void child_died(int x)
00194 {
00195   not_done=(1!=1) ;
00196   if( tab_comp_ptr != 0 ) {
00197        WRITELOG(st,snprintf(st,4096,"in child died, sent TeXmacs tuple\n") ) ;
00198        printf("%c(tuple \"read.ta\" \"michael\" \"there\")%c\n", DATA_BEGIN,DATA_END) ;
00199   }
00200   printf("%cverbatim:child_died, I quit.\n%c\n", DATA_BEGIN,DATA_END) ;
00201   WRITELOG(st,snprintf(st,4096,"child died\n") ) ;
00202   exit(0) ;
00203 }
00204 
00205 void something_wrong(int x)
00206 {
00207   not_done=(1!=1) ;
00208   WRITELOG(st,snprintf(st,4096,"something_wrong\n") ) ;
00209   if( tab_comp_ptr != 0 ) {
00210        printf("%c(tuple \"\" \"\" \"\")%c\n", DATA_BEGIN,DATA_END) ;
00211   }
00212   printf("%cverbatim:something_wrong, I quit.\n%c\n", DATA_BEGIN,DATA_END) ;
00213   WRITELOG(st,snprintf(st,4096,"child died\n") ) ;
00214   exit(0) ;
00215 }
00216 
00217 
00218 void copy_to_B( struct my_buffer *b, char *data, size_t count )
00219 {
00220   while( b->put + count > b->size ) {
00221     b->size *= 2 ;
00222     b->buf = (char *)realloc( b->buf, b->size ) ;
00223   }
00224   memcpy(b->buf+b->put,data,count) ;
00225   b->put += count ;
00226 }
00227 
00228 void copy_B_to_B( struct my_buffer *b, struct my_buffer *c )
00229 {
00230   ssize_t count = c->put - c->get ;
00231   while( b->put + count > b->size ) {
00232     b->size *= 2 ;
00233     b->buf = (char *)realloc( b->buf, b->size ) ;
00234   }
00235   memcpy(b->buf+b->put, c->buf + c->get,count) ;
00236   b->put += count ;
00237   c->put = c->get = 0 ;
00238 }
00239 
00240 // copy from c to b
00241 void ncopy_B_to_B( struct my_buffer *b, struct my_buffer *c, ssize_t count )
00242 {
00243   while( b->put + count > b->size ) {
00244     b->size *= 2 ;
00245     b->buf = (char *)realloc( b->buf, b->size ) ;
00246   }
00247   memcpy(b->buf+b->put, c->buf + c->get,count) ;
00248   b->put += count ;
00249   c->get += count ;
00250   if( c->put == c->get ) 
00251     c->get = c->put = 0 ; /* reset buffer */
00252 }
00253 
00254 void delete_from_B( struct my_buffer *b, int i, int count ) 
00255 {
00256   if( i+count > b->put )  {
00257        count = b->put - i ;
00258   } 
00259   if( i >= b->put ) 
00260        return ;
00261        
00262   memmove(b->buf+i, b->buf+i+count, b->put-(i+count) ) ;
00263   b->put -= count ;
00264 }
00265 
00266 
00267 void rem_nl_B( struct my_buffer *b)
00268 {
00269   int i = 0,j=0 ;
00270   for( i=b->get,j=b->get; i<b->put-1; i++) {
00271     if( b->buf[i] == 13 ) {
00272       if( b->buf[i+1] != 10 ) {
00273               b->buf[j] = 10 ;
00274               j++ ;
00275       }
00276     } else {
00277       b->buf[j] = b->buf[i] ;
00278       j++ ;
00279     }
00280   }
00281   if( b->buf[i] == 13 )
00282     b->buf[j] = 10 ;
00283   else
00284     b->buf[j] = b->buf[i] ;
00285   b->put = j+1 ;
00286 }
00287 
00288 
00289 
00290 int del_last_nl_B( struct my_buffer *b)
00291 {
00292   int count = 0 ;
00293   char *p = b->buf + b->put - 1 ;
00294   while( (b->put != b->get) && ((*p == 13) || (*p == 10)) ) {
00295     p-- ;
00296     b->put-- ;
00297     count ++ ;
00298   }
00299   return count ;
00300 }
00301 
00302 int del_first_nl_B( struct my_buffer *b)
00303 {
00304   int count = 0 ;
00305   char *p = b->buf + b->get ;
00306   while( (b->put != b->get) && ((*p == 13) || (*p == 10)) ) {
00307     p++ ;
00308     b->get++ ;
00309     count ++ ;
00310   }
00311   return count ;
00312 }
00313 
00314 
00315 int copy_to_B_del_nl( struct my_buffer *b, char *data, size_t count )
00316 {
00317   int n = 0 ;
00318   while( b->put + count > b->size ) {
00319     b->size *= 2 ;
00320     b->buf = (char *)realloc( b->buf, b->size ) ;
00321   }
00322   while( ((data[count-1] == 13) || (data[count-1]==10))&&(count>0)  ) {
00323     n++ ;
00324     count-- ;
00325   }
00326   memcpy(b->buf+b->put,data,count) ;
00327   b->put += count ;
00328   return n ;
00329 }
00330 
00331 
00332 ssize_t read_B( int fd, struct my_buffer *b, ssize_t count )
00333 {
00334   while( b->put + count > b->size ) {
00335        WRITELOG(st,snprintf(st,4096, "reallocating: old = %p size=%d\n",b->buf,b->size)) ;
00336     b->size *= 2 ;
00337     b->buf = (char *)realloc( b->buf, b->size ) ;
00338        if( b->buf == NULL ) {
00339          WRITELOG(st, snprintf(st,4096, "allocation failed!!\n") ) ;
00340        }
00341        WRITELOG(st,snprintf(st,4096, "reallocating: new = %p size=%d\n",b->buf,b->size)) ;
00342   }
00343   count = read( fd, b->buf+b->put, count ) ;
00344   if( count > 0 )
00345     b->put += count ;
00346   return count ;
00347 }
00348 
00349 
00350 int data_available_B( struct my_buffer *b)
00351 {
00352   return (b->put - b->get) ;
00353 }
00354 
00355 int write_B( int fd, struct my_buffer *b )
00356 {
00357   int nwrite =0;
00358   
00359   if( b->put > b->get ) {
00360     /* we have data available */
00361     WRITELOG(big,snprintf(big,1000,"wrote to %d:\n",fd) ) ;
00362     WRITELOG(b->buf+b->get, b->put - b->get ) ;
00363     WRITELOG(big,snprintf(big,1000,"<<\n") ) ;
00364        
00365     nwrite = write( fd, b->buf+b->get, b->put - b->get ) ;
00366     b->get += nwrite ;
00367     if( b->put == b->get ) 
00368       b->get = b->put = 0 ; /* reset buffer */
00369   }
00370   return nwrite ;
00371 }
00372 
00373 
00374 
00375 struct my_buffer *init_buffer( int size )
00376 {
00377   struct my_buffer *b = (struct my_buffer *)malloc( sizeof( struct my_buffer ) ) ;
00378   b->buf = (char *)malloc( size ) ;
00379   b->size = size ;
00380   b->get = b->put = 0 ;
00381   return b ;
00382 }
00383 
00384 
00385 int main(int arc, char *argv[])
00386 {
00387   
00388   
00389   char  name[100];
00390   
00391   int in_data = 0 ;
00392   
00393   struct my_buffer 
00394   *TEMPB ,
00395   *TXB,   /* buffer for interface with texmacs */
00396   *RB ;   /* buffer for interface with R */
00397   
00398   ssize_t nread;
00399   
00400   
00401   int i,j ;
00402   int got_prompt ;
00403   int in_quote, escaped ;
00404   int ignore=0 ;
00405   
00406   int last_nl = 0 ;
00407   
00408   
00409   char *TEXMACS_HOME_PATH, *TEXMACS_R, *TEXMACS_SEND,*TEXMACS_SEND_E, *TEXMACS_LIB, *HOME ;
00410   struct termios termi ;
00411   sigset_t sigmask, orig_sigmask;
00412   
00413   struct stat stat_buf;
00414 
00415   
00416 #ifdef USE_DEBUG
00417   if( DEBUG ) {
00418     unlink("/tmp/log") ;
00419     LOG = open("/tmp/log",O_CREAT|O_WRONLY) ;
00420   }
00421 #endif
00422   
00423   TXB = init_buffer( 4096 ) ;
00424   RB = init_buffer( 4096 ) ;
00425   TEMPB = init_buffer( 4096 ) ;
00426   
00427   HOME = getenv("HOME") ;
00428   if( TEXMACS_HOME_PATH == NULL ) HOME = "~" ;
00429 
00430   TEXMACS_HOME_PATH = getenv("TEXMACS_HOME_PATH") ;
00431   if( TEXMACS_HOME_PATH == NULL ) {
00432     TEXMACS_HOME_PATH = (char *)malloc( 4096 ) ;
00433     snprintf(TEXMACS_HOME_PATH,4096,"%s/.TeXmacs",HOME) ;
00434   }
00435   
00436   /* Lazy installing the TeXmacs package */
00437   TEXMACS_LIB = (char *)malloc(4096);
00438   snprintf(TEXMACS_LIB,4096,"%s/plugins/r/r",TEXMACS_HOME_PATH);
00439   if (stat(TEXMACS_LIB,&stat_buf))
00440     system("r_install"); 
00441   
00442   
00443   TEXMACS_R = getenv("TEXMACS_CMD") ;
00444   if( TEXMACS_R == NULL ) {
00445     TEXMACS_R = "R"; 
00446        /* ignore 1 input request - i.e. do not generate a prompt channel in
00447      texmacs for it */
00448     ignore=1;
00449   } else {
00450     ignore=0;
00451   }
00452   
00453   TEXMACS_SEND_E = getenv("TEXMACS_SEND") ;
00454   TEXMACS_SEND = (char *)malloc( 4096 ) ;
00455 #if 1
00456   if( TEXMACS_SEND_E == NULL ) {
00457     snprintf(TEXMACS_SEND,4096,"library(TeXmacs,lib.loc=paste(Sys.getenv(\"HOME\"),\"/.TeXmacs/plugins/r/r/\",sep=\"\"))\n") ;
00458   } else {
00459     snprintf(TEXMACS_SEND,4096,"%s\n",TEXMACS_SEND_E) ;
00460   }
00461 #endif
00462   
00463   /* prepare for the string to be sent to the process */
00464   copy_to_B( RB, st, snprintf( st,4096, "%s",TEXMACS_SEND) ) ;
00465   
00466   
00467   if( (childpid=forkpty( &master, name, NULL, NULL ))==0 ) {
00468     /* I'm the child - I'll run the command */
00469     char **exec_argv ;
00470     int i,n,m ;
00471     m = strlen( TEXMACS_R ) ;
00472     for( i=0,n=0; i<m; i++)
00473       if( TEXMACS_R[i] == ' ' ) 
00474               n++ ;
00475        
00476     exec_argv = (char **) malloc( (n+2)*sizeof( char * ) ) ;
00477        
00478     /* split TEXMACS_R into arguments into exec_argv, 
00479         at each " " that doesn't have a \ to escape it  */
00480     exec_argv[0] = TEXMACS_R ;
00481     for( i=0,n=0; i<m; i++)
00482       if( (TEXMACS_R[i] == ' ') && (i>0) && (TEXMACS_R[i-1]!='\\') ) {
00483               n++ ;
00484               exec_argv[n] = TEXMACS_R+i+1 ;
00485               TEXMACS_R[i] = 0 ;
00486       }
00487     exec_argv[n+1] = NULL ;
00488     execvp(TEXMACS_R,exec_argv) ;
00489   } else {
00490     /* I'm the parent - I'll handle input and output and watch the child.*/
00491        
00492     /* This is for pselect. Supposedly if pselect doesn't know what signals
00493         we are waiting for, it will get confused. */
00494     sigemptyset (&sigmask);
00495     sigaddset (&sigmask, SIGCHLD);
00496     sigaddset (&sigmask, SIGINT);
00497     sigaddset (&sigmask, SIGILL);
00498     sigaddset (&sigmask, SIGSEGV);
00499     sigaddset (&sigmask, SIGABRT);
00500     sigaddset (&sigmask, SIGBUS);
00501     sigprocmask (SIG_BLOCK, &sigmask,
00502                              &orig_sigmask);
00503        
00504     signal (SIGINT, signal_int);
00505     signal (SIGCHLD, child_died);
00506        signal (SIGBUS, something_wrong ) ;
00507        signal (SIGABRT, something_wrong ) ;
00508        signal (SIGILL, something_wrong ) ;
00509        signal (SIGSEGV, something_wrong ) ;
00510        
00511     fcntl(master, F_SETFL, O_NONBLOCK) ;
00512        
00513     /* send the initial string */
00514     write_B( master, RB ) ;
00515        
00516     /* get terminal settings */
00517     tcgetattr(master, &termi ) ;
00518 #if VERBOSE_TERM
00519     printf("%x %x %x %x\n",termi.c_iflag,termi.c_oflag,termi.c_lflag,termi.c_lflag&ECHO) ;
00520 #endif
00521     termi.c_lflag &= ~ECHO  ; /* no echo */
00522     tcsetattr(master,TCSANOW, &termi ) ;
00523        
00524 #if VERBOSE_TERM
00525     printf("%x %x %x %x\n",termi.c_iflag,termi.c_oflag,termi.c_lflag,termi.c_lflag&ECHO) ;
00526 #endif
00527     
00528        
00529     
00530     while(not_done) {
00531       /* prepare the file sets for select to watch */
00532       fd_set rd, wr, er;
00533       WRITELOG("<<<\n",4) ;
00534          
00535       FD_ZERO (&rd);
00536       FD_ZERO (&wr);
00537       FD_ZERO (&er);
00538       FD_SET (master, &rd);
00539          
00540       
00541       if( data_available_B( RB ) )  /* if we have data available to send,  */
00542            FD_SET (master, &wr);       /*  then also wait to send. */
00543          
00544       FD_SET (STDIN_FILENO, &rd ) ;
00545          
00546 #define WAIT_FOR_OUT
00547 #ifdef WAIT_FOR_OUT
00548       if( data_available_B( TXB ) )
00549            FD_SET (STDOUT_FILENO, &wr ) ;
00550 #endif
00551          
00552       /* Main pselect switch --------------- */
00553       if( pselect( master+1, &rd, &wr, &er, NULL, &orig_sigmask ) > 0 ) {
00554            if( FD_ISSET( STDIN_FILENO, &rd ) ) {
00555              /* =============== read input from TeXmacs */
00556              nread = read_B( STDIN_FILENO, RB, 1000 ) ;
00557              if( (nread > 2 ) &&
00558                       (RB->buf[RB->put-nread]   == '@' ) &&
00559                       (RB->buf[RB->put+1-nread] == '@' ) &&
00560                       (RB->buf[RB->put+2-nread] == '@' )
00561                       ) {
00562                      RB->put -= nread ;
00563                 } else {
00564                      for(i=0; i<nread-1; i++) {
00565                        WRITELOG(st,snprintf(st,4096,":%d:%c", RB->buf[RB->put+i-nread], RB->buf[RB->put+i-nread]) ) ;
00566                        
00567                        /* What is this:? */
00568                        if( (RB->buf[RB->put+i-nread]==';') &&  (RB->buf[RB->put+i-nread+1]==';') )
00569                        {
00570                             RB->buf[RB->put+i-nread] = ' ' ; /* This is space then delete */
00571                             RB->buf[RB->put+i-nread+1] = 10 ;
00572                        } 
00573                        else 
00574                             if( RB->buf[RB->put+i-nread]==DATA_COMMAND)
00575                             {
00576                               if (!tab_comp_ptr)
00577                               {
00578                                    ignore=0 ;
00579                                    WRITELOG(st,snprintf(st,4096,"TeXmacs completion!!!\n") ) ;
00580                                    WRITELOG(st,snprintf(st,4096,"com: %s\n",&(RB->buf[RB->put+i-nread+1])) ) ;
00581                                    
00582                                    strncpy(RB->buf+RB->put-nread,"t.tab.comp",10);
00583                                    tab_comp_ptr=1;
00584                                    //i += 10 ; //
00585                                    i=10;
00586                                    RB->buf[RB->put+(i)-nread] = '(' ; //
00587                                    
00588                                    //     strncpy(RB->buf+RB->put-nread, temp_buf, tab_comp_ptr);
00589                                    in_quote = 0 ; escaped = 0 ;
00590                                    for(i++;i<nread-1;i++) {
00591                                      // WRITELOG(st,snprintf(st,4096,"i:%d nread:%d in_q: %d, esc: %d, chr:%s\n",i,nread,in_quote,escaped,&(RB->buf[RB->put+(i)-nread]))) ;
00592                                      if(in_quote == 0 ) {
00593                                           if( RB->buf[RB->put+(i)-nread]==' ') {  
00594                                             WRITELOG(st,snprintf(st,4096,"found space\n")) ;
00595                                             RB->buf[RB->put+(i)-nread] = ',' ;      
00596                                             break ;
00597                                           }
00598                                      } 
00599                                      if ( (in_quote==0) && ( RB->buf[RB->put+(i)-nread]=='"') && ( RB->buf[RB->put+(i)-nread-1]=='"')) {
00600                                           WRITELOG(st,snprintf(st,4096,"found double quote\n")) ;
00601                                           printf("\2scheme:(tuple \"\" \"\")\5");
00602                                           fflush(stdout);
00603                                           i=nread;
00604                                           break;
00605                                      }
00606                                      
00607                                      if( (escaped == 0) && (RB->buf[RB->put+(i)-nread]=='"') ) 
00608                                           in_quote = 1-in_quote ;
00609                                      if( (escaped == 0 ) && (RB->buf[RB->put+(i)-nread]=='\\') ) {
00610                                           escaped = 1 ;
00611                                      } else {
00612                                           escaped = 0 ;
00613                                      }
00614                                    }
00615                                    
00616                                    break;
00617                                    
00618                               } else {
00619                                    
00620                                    RB->put=RB->get=0;
00621                                    break;
00622                                    
00623                               }
00624                             }
00625                      }
00626                 }
00627               }
00628               
00629               if( FD_ISSET( master, &rd ) ) {
00630                 /* =================== read input from sub process (R) */
00631                 while( read_B( master, TEMPB, 4096) > 0 ) 
00632                      usleep(5) ;
00633                 
00634                 got_prompt = check_terminal( master ) || check_prompt_strings_B( TEMPB ) ;
00635                 
00636                 if (tab_comp_ptr) {
00637                      WRITELOG(st,snprintf(st,4096, "in if(tab_comp_ptr)\n") ) ;
00638                      if( TEMPB == NULL ) {
00639                        WRITELOG(st,snprintf(st,4096,"TEMPB is null\n")) ;
00640                      } else {
00641                        WRITELOG(st, snprintf(st,4096,"get = %d, put=%d size=%d buf=%p\n",TEMPB->get,TEMPB->put,TEMPB->size,TEMPB->buf)) ;
00642 //                     WRITELOG(st, snprintf(st,4096,"get = %d, put=%d size=%d buf=%p\n",TEMPB->get,TEMPB->put,TEMPB->size,TEMPB->buf)) ;
00643                        if( TEMPB->buf == NULL ) {
00644                             WRITELOG(st,snprintf(st,4096,"TEMPB buf is null\n")) ;
00645                        } else {
00646                             WRITELOG(st,snprintf(st,4096, "temp buf is %s\n",TEMPB->buf)) ;
00647                        }
00648                        
00649                      }
00650                      for (i=TEMPB->get,j=TEMPB->get;i<TEMPB->put;i++)
00651                      {
00652                        WRITELOG(st,snprintf(st,4096,"i=%d %s\n",i,TEMPB->buf+i)) ;
00653                        if ( (TEMPB->buf[i]=='\2') && (j==TEMPB->get ) ) {
00654                             WRITELOG(st,snprintf(st,4096,"found begin, moved j by %d\n",i-j)) ;
00655                             j=i ;
00656                        }
00657                        if (TEMPB->buf[i]=='\5') {       
00658                             WRITELOG(st,snprintf(st,4096,"found end, total length %d\n",i-j)) ;
00659                             fwrite( TEMPB->buf+j, 1, i - j + 1, stdout) ;
00660                             TEMPB->get=i+1;
00661                             tab_comp_ptr=0;
00662                             fflush(stdout);
00663                             break;
00664                        }
00665                      }
00666                 }
00667 //              if( got_prompt ) 
00668                      tab_comp_ptr = 0 ;
00669                 
00670                 if( tab_comp_ptr ) 
00671                      TEMPB->get = TEMPB->put ;
00672                 
00673                 //fflush(ffile);
00674                 //            tab_comp_ptr=0;
00675                 
00676                 if( (got_prompt  ) && (ignore==0) )  { 
00677                      /* find the previous end-of-line, and use that for the
00678                       prompt */
00679                      for( i= TEMPB->put - TEMPB->get; i > 0; i--) 
00680                        if( (TEMPB->buf[i-1]==13) || (TEMPB->buf[i-1]==10) ) 
00681                             break ;
00682                      if( i > 0 ) {
00683 #if 0
00684                        if( TEMPB->buf[TEMPB->get] == DATA_BEGIN ) {
00685                             ncopy_B_to_B( TXB, TEMPB, i ) ;
00686                        } else 
00687 #endif
00688                        {
00689                             IN_VERBATIM( TXB ) ;
00690                             /* print everything before the previous end-of-line */
00691                             while( last_nl > 0 ) {
00692                               copy_to_B( TXB, "\n", 1 ) ;
00693                               last_nl-- ;
00694                             } 
00695                             /* print everything before the pervious end-of-line */
00696                             WRITELOG(st,snprintf(st,4096,"copy 1\n") ) ;
00697                             ncopy_B_to_B( TXB, TEMPB, i ) ;
00698                             del_last_nl_B( TXB ) ;
00699                        }
00700                      }
00701                      del_first_nl_B( TEMPB ) ;
00702                      IN_VERBATIM( TXB ) ;
00703                      
00704                      if( data_available_B( TEMPB) ) {
00705                        
00706                        last_nl = 0 ;
00707                        B_DATA_BEGIN( TXB) ; {
00708                             copy_to_B( TXB, st, snprintf(st,4096,"prompt#") ) ;
00709                             B_DATA_BEGIN( TXB ) ; 
00710                             {
00711                               copy_to_B( TXB, st, snprintf(st,4096,"latex:\\red ") ) ;
00712                               WRITELOG(st,snprintf(st,4096,"copy 2\n") ) ;                          
00713                               copy_B_to_B( TXB, TEMPB ) ;
00714                               copy_to_B( TXB, st, snprintf(st,4096,"\\black") ) ;
00715                             } 
00716                             B_DATA_END( TXB ) ;
00717                        }
00718                        B_DATA_END( TXB ) ;
00719                      } 
00720                      END_VERBATIM( TXB ) ;
00721                 } else {
00722                      if( got_prompt && (ignore > 0) ) 
00723                        ignore-- ;
00724                      /* terminal is not waiting for user - just print data. */
00725 #if 0
00726                      if( TEMPB->buf[TEMPB->get] == DATA_BEGIN ) {
00727                        copy_B_to_B( TXB, TEMPB ) ;
00728                      } else 
00729 #endif
00730                      {
00731                        IN_VERBATIM( TXB ) ;
00732                        while( last_nl > 0 ) {
00733                             copy_to_B( TXB, "\n", 1 ) ;
00734                             last_nl-- ;
00735                        }
00736 //                     WRITELOG(st,snprintf(st,4096,"before last: %s\n",TEMPB->buf + TEMPB->get)) ;
00737                        copy_B_to_B( TXB, TEMPB ) ;
00738 //                     WRITELOG(st,snprintf(st,4096,"after last: \n")) ;
00739                        last_nl = del_last_nl_B( TXB ) ;
00740                      }
00741                 } 
00742                 
00743               }
00744 #ifdef WAIT_FOR_OUT
00745               if( FD_ISSET( STDOUT_FILENO, &wr ) ) {
00746 #endif
00747                 /* ================= TeXmacs is ready to receive data */
00748                 rem_nl_B( TXB ) ;
00749                 write_B( STDOUT_FILENO, TXB ) ;
00750 #ifdef WAIT_FOR_OUT
00751               }
00752 #endif
00753               if( FD_ISSET( master, &wr ) ) {
00754                 /* ================= Terminal is ready to receive data */
00755                 if( RB->put > RB->get ) {
00756                      tcgetattr(master, &termi ) ;
00757                      termi.c_lflag |= ECHO  ; /* no echo */
00758                      termi.c_lflag ^= ECHO  ; /* no echo */
00759                      /* set tserminal settings */
00760                      tcsetattr(master,TCSANOW, &termi ) ;
00761                      
00762                      write_B( master, RB ) ;
00763                 }
00764               }
00765               
00766               
00767          }
00768        }
00769        
00770   }
00771   exit(0) ;
00772 }
00773 
00774 
00775 
00776 
00777 
00778 #if 0
00779 temp_buf=(char*)malloc(RB->size+10+6+1000);
00780 strncpy(temp_buf,"t.tab.comp",10) ;
00781 tab_comp_ptr=10;
00782 temp_buf[tab_comp_ptr++] = '(';
00783 
00784 temp_buf[tab_comp_ptr++] = '"';
00785 strncpy(&temp_buf[tab_comp_ptr], &RB->buf[RB->put-nread], i);
00786 tab_comp_ptr+=i;
00787 temp_buf[tab_comp_ptr++] = '"';
00788 temp_buf[tab_comp_ptr++] = ',';
00789 tab_comp_ptr+=sprintf(&temp_buf[tab_comp_ptr],"%d",i);
00790 temp_buf[tab_comp_ptr++] = ')';
00791 temp_buf[tab_comp_ptr++] = '\n';
00792 RB->put-=nread;
00793 while ((RB->put+tab_comp_ptr) > RB->size)
00794 {
00795   RB->size *= 2 ;
00796   RB->buf = (char *)realloc( RB->buf, RB->size ) ;
00797 }
00798 strncpy(RB->buf+RB->put, temp_buf, tab_comp_ptr);
00799 RB->put+=tab_comp_ptr;
00800 nread=tab_comp_ptr;
00801 
00802 free(temp_buf);
00803 #endif