Nife version Beta
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

493 lines
14 KiB

  1. /* Copyright (C) 2011-2022 Patrick H. E. Foubet - S.E.R.I.A.N.E.
  2. This program is free software: you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation, either version 3 of the License, or any
  5. later version.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program. If not, see <http://www.gnu.org/licenses/>
  12. *******************************************************************/
  13. /* histo.c */
  14. #include "conf.h"
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <signal.h>
  19. #include <sys/types.h>
  20. #include <sys/wait.h>
  21. #include <sys/stat.h>
  22. #include <fcntl.h>
  23. #include <termios.h>
  24. #include <unistd.h>
  25. #include "histo.h"
  26. #include "nife.h"
  27. #include "mth.h"
  28. #include "err.h"
  29. #include "lib.h"
  30. #include "debug.h"
  31. #define HISTOMAX 100
  32. static char * HIST[HISTOMAX];
  33. static int iH=0, iHt, iHl, iHFull=0;
  34. #define FDMAX 128
  35. static int iFD=0;
  36. static int FD_T[FDMAX], FD_L[FDMAX]; /* fd table and line numbers */
  37. static void *FD_N[FDMAX];
  38. void IF_showFD(void)
  39. {
  40. printf("iFD=%d FD_T=%d FD_L=%d\n",iFD, FD_T[iFD], FD_L[iFD]);
  41. }
  42. void addFD(int fd, char*S)
  43. {
  44. void *M;
  45. iFD++;
  46. /* printf("addFD iFD=%d\n",iFD); */
  47. if (iFD == FDMAX) {
  48. iFD--;
  49. messErr(45);
  50. return;
  51. }
  52. _MODIF_FD_IN_(fd);
  53. FD_T[iFD]=fd;
  54. FD_L[iFD]=0;
  55. if ((M = malloc(strlen(S)+1)) == NULL) stopErr("addFD","malloc");
  56. #ifdef DEBUG_M
  57. printf("New String address : %lu \n",(unsigned long)M);
  58. #endif
  59. strcpy((char*)M,S);
  60. FD_N[iFD]=M;
  61. }
  62. void closeFD(void)
  63. {
  64. /* printf("closeFD iFD=%d\n",iFD); */
  65. close(FD_IN);
  66. free(FD_N[iFD]);
  67. iFD--;
  68. if (iFD) _MODIF_FD_IN_(FD_T[iFD]);
  69. else _MODIF_FD_IN_(0);
  70. }
  71. int getiFD(void)
  72. {
  73. return iFD;
  74. }
  75. int getFDlig(void)
  76. {
  77. return FD_L[iFD];
  78. }
  79. char * getFDname(void)
  80. {
  81. return (char*)FD_N[iFD];
  82. }
  83. void incFDlig(void)
  84. {
  85. FD_L[iFD]++;
  86. }
  87. void razHisto(void)
  88. {
  89. int i;
  90. for(i=0;i<iH;i++) free((void*)HIST[i]);
  91. iH=0;
  92. }
  93. void putHisto(char *C)
  94. {
  95. int L;
  96. if ((L=strlen(C)) == 0) return;
  97. HIST[iH] = (char*)malloc(L+1);
  98. if (HIST[iH] != NULL) {
  99. strcpy(HIST[iH],C);
  100. iHt=iH; /* depart recherche */
  101. iH++;
  102. iHl=iH;
  103. if (iH == HISTOMAX) {
  104. iHFull=1;
  105. iH=0;
  106. }
  107. }
  108. }
  109. char * getHisto(char S) /* Sens A remonte, B descend */
  110. {
  111. char * C;
  112. if (S == 'B') {
  113. if (iHt == iH-1) {
  114. iHl=iH;
  115. printf("\a");
  116. fflush(stdout);
  117. C = NULL;
  118. } else {
  119. iHt++;
  120. if (iHt == HISTOMAX) iHt=0;
  121. if (iHl==iHt) iHt++;
  122. C = HIST[iHt];
  123. iHl=iHt;
  124. }
  125. } else { /* A */
  126. if (iHt == -1) {
  127. iHl=iHt;
  128. printf("\a");
  129. fflush(stdout);
  130. C = NULL;
  131. } else {
  132. if (iHl==iHt) iHt--;
  133. iHl=iHt;
  134. C = HIST[iHt--];
  135. if ((iHt < 0) && (iHFull)) iHt = HISTOMAX-1;
  136. }
  137. }
  138. return(C);
  139. }
  140. static struct termios t0, t1;
  141. int iTERM=0;
  142. void termInit(void)
  143. {
  144. int nc;
  145. for (iTERM=0; iTERM<3; iTERM++) {
  146. if (tcgetattr(iTERM, &t0) != -1) break;
  147. if (iTERM<2) continue;
  148. perror("No terminal found ! tcgetattr"); /* sauvegarde */
  149. exit(2);
  150. }
  151. if (tcgetattr(iTERM, &t1) == -1) perror("tcgetattr");
  152. /* cfmakeraw(&t1); */
  153. t1.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
  154. | INLCR | IGNCR | ICRNL | IXON);
  155. /* t1.c_oflag &= ~OPOST; */
  156. /* t1.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); */
  157. t1.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN);
  158. t1.c_cflag &= ~(CSIZE | PARENB);
  159. t1.c_cflag |= CS8;
  160. if (tcsetattr(iTERM, TCSAFLUSH, &t1) == -1) perror("tcsetattr"); /* raw */
  161. /* clear screen */
  162. nc=system("clear");
  163. }
  164. void termReset(void)
  165. {
  166. if (tcsetattr(iTERM, TCSAFLUSH, &t0) == -1) perror("tcsetattr");/*restaure*/
  167. }
  168. void enleve1(char * s)
  169. {
  170. char * w;
  171. w=s;
  172. while (*w != '\0') *w++ = *(w+1);
  173. }
  174. void insertC(char c, char * s)
  175. {
  176. char *w;
  177. w=s;
  178. while (*w != '\0') w++;
  179. while (w >= s) { *(w+1) = *w; w--; }
  180. *s=c;
  181. }
  182. int lireLigne(int fd, char *b, char *s, int nc)
  183. /* fd = file descriptor
  184. b = adresse du buffer
  185. nc = nb de caracteres possible (longueur du buffer */
  186. {
  187. char *d, *f, c, c2, c3, *h, *w, *Wl, *rac;
  188. int n, i, l, ls=0, ins=0, ignTild=0, nbT=0, Nc;
  189. unsigned int j;
  190. char bufd[50];
  191. /* printf("lireLigne ... \n"); */
  192. d = b;
  193. f = b+nc;
  194. while(d<f-ls) {
  195. if (noErr()) {
  196. n = -1;
  197. break;
  198. }
  199. /* fprintf(stderr,"d-b=%d ins=%d s=<%s> b=<%s>\n",d-b,ins,s,b); */
  200. if ((n=read(fd,d,1)) != 1) break;
  201. c=*d;
  202. if (ignTild && (c == '~')) {
  203. ignTild=0; continue;
  204. }
  205. if ((c > 31) && (c < 127)) { /* de SPACE a TILDE */
  206. if (!((FD_IN || iTERM) && ECHOOFF)) {
  207. printf("%c",c);
  208. if (ins) {
  209. if (ins==2) /* rewrite */
  210. enleve1(s);
  211. if(*s =='\0') ins=0;
  212. else {
  213. printf("%s",s);
  214. for (j=0; j<strlen(s); j++) printf("\b");
  215. }
  216. }
  217. }
  218. fflush(stdout);
  219. d++;
  220. } else {
  221. switch (c) {
  222. /* Ctrl C
  223. case '\003' :
  224. kill(getpid(), SIGINT);
  225. break; */
  226. case '\t': /* tab */
  227. if (d>b) {
  228. *d='\0';
  229. w=d-1;
  230. while ((w>b) && (!(isSepa(*w,1)))) w--;
  231. if (isSepa(*w,0)) w++;
  232. /* fprintf(stderr,"d-b=%d w=<%s>\n",d-b,w); */
  233. if (strlen(w) > 0) {
  234. j=nbLibBegin(w, &rac);
  235. /* fprintf(stderr,"j=%d w=<%s>\n",j,w); */
  236. if (j==0) printf("\a");
  237. else {
  238. if (j==1) {
  239. Wl=getLibBegin(w);
  240. i=strlen(Wl)-strlen(w);
  241. /* fprintf(stderr,"i=%d Wl=<%s>\n",i,Wl); */
  242. if (i>0) {
  243. strcpy(w,Wl);
  244. printf("%s ",d);
  245. d+=i;
  246. *d++ = ' ';
  247. if (ins) {
  248. printf("%s ",s);
  249. for (j=0; j<(strlen(s)+1); j++) printf("\b");
  250. }
  251. } else { /* XXXX */
  252. if (i==0) {
  253. printf (" ");
  254. *d++ = ' ';
  255. }
  256. }
  257. } else {
  258. if (rac != NULL) {
  259. i=strlen(rac)-strlen(w);
  260. strcpy(w,rac);
  261. printf("%s",d);
  262. d+=i;
  263. if (ins) {
  264. printf("%s ",s);
  265. for (j=0; j<(strlen(s)+1); j++) printf("\b");
  266. }
  267. } else {
  268. nbT++;
  269. if (nbT>1) {
  270. nbT=0;
  271. printf("\n");
  272. listLibBegin(w);
  273. *d='\0';
  274. printf("> %s",b);
  275. if (ins) {
  276. printf("%s ",s);
  277. for (j=0; j<(strlen(s)+1); j++) printf("\b");
  278. }
  279. fflush(stdout);
  280. }
  281. }
  282. }
  283. }
  284. fflush(stdout);
  285. }
  286. }
  287. break;
  288. case '\177':
  289. if (d>b) {
  290. printf("\b \b");
  291. if (ins) {
  292. printf("%s ",s);
  293. for (j=0; j<(strlen(s)+1); j++) printf("\b");
  294. }
  295. fflush(stdout);
  296. d--;
  297. }
  298. break;
  299. case '\n':
  300. case '\r':
  301. if ((FD_IN || iTERM) && ECHOOFF) printf(".");
  302. else {
  303. printf("\n");
  304. if (ins) {
  305. if (d+strlen(s) < f) {
  306. sprintf(d,"%s",s);
  307. d+=strlen(s);
  308. } else return(-1);
  309. }
  310. }
  311. goto finBoucle;
  312. /* gestion des caracteres speciaux */
  313. case '\033': /* ESCAPE */
  314. ignTild=1;
  315. Nc=read(fd,&c2,1);
  316. Nc=read(fd,&c3,1);
  317. if (c2 == '[') { /* CSI - see XTerm Control Sequences */
  318. switch(c3) {
  319. case '2' : /* Insert */
  320. if (ins) {
  321. ins++;
  322. if (ins==3) ins=1;
  323. }
  324. break;
  325. case '3' : /* Suppr */
  326. if (ins) {
  327. enleve1(s);
  328. if(*s =='\0') ins=0;
  329. printf("%s \b",s);
  330. for (j=0; j<strlen(s); j++) printf("\b");
  331. fflush(stdout);
  332. }
  333. break;
  334. case 'A' : /* UpArrow */
  335. case 'B' : /* DownArrow */
  336. ins = 0;
  337. /* efface la ligne en cours */
  338. l=d-b;
  339. for(i=0;i<l;i++) printf("\b \b");
  340. fflush(stdout);
  341. d=b;
  342. *d = '\0';
  343. if ((h=getHisto(c3)) != NULL) {
  344. strcpy(b,h);
  345. d=b+strlen(h);
  346. /*
  347. printf("\n%s (iH=%d iHt=%d)\n",h,iH,iHt);
  348. *d='\0';
  349. */
  350. printf("%s",b);
  351. fflush(stdout);
  352. }
  353. break;
  354. case 'C' : /* -> */
  355. if (ins) {
  356. *d = *s;
  357. printf("%c",*d++);
  358. enleve1(s);
  359. if(*s =='\0') ins=0;
  360. else {
  361. printf("%s",s);
  362. for (j=0; j<strlen(s); j++) printf("\b");
  363. }
  364. fflush(stdout);
  365. }
  366. break;
  367. case 'D' : /* <- */
  368. if (d>b) {
  369. if (ins==0) {
  370. ins=1;
  371. *d='\0';
  372. strcpy(s,d-1);
  373. } else insertC(*(d-1),s);
  374. d--;
  375. printf("\b");
  376. fflush(stdout);
  377. }
  378. break;
  379. case 'H' : /* home : debug terms ON */
  380. case '1' : /* home numeric */
  381. IFD_DebugTOn();
  382. break;
  383. case 'F' : /* end : debug terms OFF */
  384. case '4' : /* end numeric */
  385. IFD_DebugTOff();
  386. break;
  387. default:
  388. sprintf(bufd,"# ignore : ESC [ %d (%c) !",(int)c3, c3);
  389. D_Tracenl(bufd);
  390. *d='\0';
  391. /* **************
  392. printf("> %s",b);
  393. fflush(stdout); */
  394. }
  395. } else {
  396. if (c2 == 'O') { /* SS3 - see XTerm Control Sequences */
  397. switch(c3) {
  398. case 'P' : /* F1 */
  399. break;
  400. case 'Q' : /* F2 */
  401. break;
  402. case 'R' : /* F3 */
  403. break;
  404. case 'S' : /* F4 */
  405. break;
  406. case 'H' : /* home : debug terms ON */
  407. IFD_DebugTOn();
  408. break;
  409. case 'F' : /* end : debug terms OFF */
  410. IFD_DebugTOff();
  411. break;
  412. }
  413. } else {
  414. sprintf(bufd,"# ignore : ESC %d %d (%c) !",(int)c2,(int)c3, c3);
  415. D_Tracenl(bufd);
  416. *d='\0';
  417. /* **************
  418. printf("> %s",b);
  419. fflush(stdout); */
  420. }
  421. }
  422. break;
  423. default :
  424. /*
  425. printf("\nCar = %d !\n",(int)c);
  426. *d='\0';
  427. printf("> %s",b);
  428. fflush(stdout);
  429. */
  430. break;
  431. }
  432. }
  433. if (ins) ls = strlen(s);
  434. }
  435. finBoucle:
  436. /* printf("fin lireLigne!\n"); */
  437. if ((n<1) && (FD_IN !=0)) {
  438. closeFD(); /* fichier loader */
  439. if (ECHOOFF) printf("\n");
  440. return 0;
  441. }
  442. if ((n<1) && iTERM) {
  443. close(FD_IN); /* pipe ou autre */
  444. Nc=dup(iTERM); /* stdin on term */
  445. iTERM = 0;
  446. if (ECHOOFF) printf("\n");
  447. return 0;
  448. }
  449. if (d == f) { /* cas du buffer trop petit */
  450. /* d=b;
  451. while (*d != '\n') read(fd,d,1);
  452. **** not in raw mode */
  453. #ifdef DEBUG
  454. printf("lireLigne : erreur !\n");
  455. #endif
  456. return(-1);
  457. }
  458. *d = '\0';
  459. #ifdef DEBUG
  460. printf("lireLigne : retour <%s> !\n",b);
  461. #endif
  462. if (!FD_IN) putHisto(b);
  463. incFDlig();
  464. return(strlen(b));
  465. }