source: vis_dev/vis-2.3/src/cmd/cmdFile.c @ 36

Last change on this file since 36 was 14, checked in by cecile, 13 years ago

vis2.3

File size: 23.2 KB
Line 
1/**CFile***********************************************************************
2
3  FileName    [cmdFile.c]
4
5  PackageName [cmd]
6
7  Synopsis    [File open, and file completion.]
8
9  Author      [Originated from SIS]
10
11  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
12  All rights reserved.
13
14  Permission is hereby granted, without written agreement and without license
15  or royalty fees, to use, copy, modify, and distribute this software and its
16  documentation for any purpose, provided that the above copyright notice and
17  the following two paragraphs appear in all copies of this software.
18
19  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
20  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
21  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
22  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
24  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
25  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
26  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
27  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
28  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
29
30******************************************************************************/
31
32#include "cmdInt.h"
33
34#if HAVE_READLINE_READLINE_H
35#include <readline/readline.h>
36#else
37EXTERN char *readline(char *);
38#endif
39#if HAVE_READLINE_HISTORY_H
40#include <readline/history.h>
41#else
42EXTERN void add_history(char *);
43#endif
44
45static char rcsid[] UNUSED = "$Id: cmdFile.c,v 1.24 2009/04/11 18:25:50 fabio Exp $";
46
47/*---------------------------------------------------------------------------*/
48/* Constant declarations                                                     */
49/*---------------------------------------------------------------------------*/
50#ifdef ESC
51#undef ESC
52#endif
53#define ESC     '\033'
54#define BEEP    '\007'
55#define HIST    '%'
56#define SUBST   '^'
57
58#define STDIN   0
59#define STDOUT  1
60
61
62/*---------------------------------------------------------------------------*/
63/* Variable declarations                                                     */
64/*---------------------------------------------------------------------------*/
65static char visHistChar = HIST;       /* can be changed by "set hist_char" */
66static char *seperator = " \t\n;";
67
68
69/**AutomaticStart*************************************************************/
70
71/*---------------------------------------------------------------------------*/
72/* Static function prototypes                                                */
73/*---------------------------------------------------------------------------*/
74
75#if HAVE_IOCTL_WITH_TIOCGETC
76static int cmp(const void * s1, const void * s2);
77static int match(char * newmatch, char * lastmatch, char * actual);
78#endif
79static int getnum(char ** linep);
80static char * getarg(char * line, int num);
81static char * bad_event(int n);
82static char * do_subst(char * dest, char * new_);
83static void print_prompt(char * prompt);
84#if HAVE_LIBREADLINE
85static char * removeWhiteSpaces(char *string);
86#endif
87
88/**AutomaticEnd***************************************************************/
89
90
91/*---------------------------------------------------------------------------*/
92/* Definition of exported functions                                          */
93/*---------------------------------------------------------------------------*/
94
95
96
97/**Function********************************************************************
98
99  Synopsis    [Opens the file with the given mode.]
100
101  Description [Opens the file with the given mode (see fopen()).  Tilde
102  expansion (~user/ or ~/) is performed on the fileName, and "-" is allowed as
103  a synonym for stdin (or stdout, depending on the mode).  If the file cannot
104  be opened, a message is reported using perror(); the silent flag, if true,
105  suppresses this error action.  In either case, A NULL file pointer is
106  returned if any error occurs.  The fileName (after tilde expansion) is
107  returned in the pointer realFileName, if realFileName is non-empty.  This
108  is a pointer which should be free'd when you are done with it.]
109
110  SideEffects []
111
112******************************************************************************/
113FILE *
114Cmd_FileOpen(
115  char * fileName,
116  char * mode,
117  char ** realFileName_p,
118  int  silent)
119{
120  char *realFileName, *path, *user_path;
121  char *lib_name;
122  FILE *fp;
123
124  if (strcmp(fileName, "-") == 0) {
125    if (strcmp(mode, "w") == 0) {
126      realFileName = util_strsav("stdout");
127      fp = stdout;
128    }
129    else {
130      realFileName = util_strsav("stdin");
131      fp = stdin;
132    }
133  }
134  else {
135    realFileName = NIL(char);
136    if (strcmp(mode, "r") == 0) {
137      user_path = Cmd_FlagReadByName("open_path");
138      if (user_path != NIL(char)) {
139        lib_name = Vm_VisObtainLibrary();
140        path = ALLOC(char, strlen(user_path)+strlen(lib_name)+10);
141        (void) sprintf(path, "%s:%s", user_path, lib_name);
142
143        /*
144         * If the fileName begins with ./, ../, ~/, or /, AND the file doesn't
145         * actually exist, then VIS will look in the open path (which includes
146         * the sis library) for the file.  This could lead to unexpected behavior:
147         * the user is looking for ./msu.genlib, and since that isn't there, the
148         * users gets sis_lib/msu.genlib, and no error is reported.  The following
149         * pseudo code fixes this:
150         *
151         * if (the beginning of file_name is : ./ || ../ || ~/ || /) {
152         * realFileName = util_file_search(fileName, NIL(char), "r");
153         * } else
154         */
155        realFileName = util_file_search(fileName, path, "r");
156        FREE(path);
157        FREE(lib_name);
158      }
159    }
160    if (realFileName == NIL(char)) {
161      realFileName = util_tilde_expand(fileName);
162    }
163    if (strcmp(mode, "r") == 0 && !util_check_file(realFileName, mode)) {
164      FREE(realFileName);
165      return NIL(FILE);
166    }
167    if ((fp = fopen(realFileName, mode)) == NIL(FILE)) {
168      if (! silent) {
169        perror(realFileName);
170      }
171    }
172  }
173  if (realFileName_p != 0) {
174    *realFileName_p = realFileName;
175  }
176  else {
177    FREE(realFileName);
178  }
179  return fp;
180}
181
182/*---------------------------------------------------------------------------*/
183/* Definition of internal and static functions                               */
184/*---------------------------------------------------------------------------*/
185
186#if HAVE_IOCTL_WITH_TIOCGETC
187
188/*
189 * Words are seperated by any of the characters in `seperator'.  The seperator
190 * is used to distinguish words from each other in file completion and history
191 * substitution. The recommeded seperator string is " \t\n;".
192 */
193
194static int cmp(const void * s1, const void * s2);
195static int match(char * newmatch, char * lastmatch, char * actual);
196static int getnum(char ** linep);
197
198/**Function********************************************************************
199
200  Synopsis [Duplicates the function of fgets, but also provides file
201  completion in the same style as csh]
202
203  Description [ Input is read from `stream' and returned in `buf'.  Up to
204  `size' bytes will be placed into `buf'.  If `stream' is not stdin, is
205  equivalent to calling fgets(buf, size, stream).
206
207  `prompt' is the prompt you want to appear at the beginning of the line.  The
208  caller does not have to print the prompt string before calling this routine.
209  The prompt has to be reprinted if the user hits ^D.
210
211  The file completion routines are derived from the source code for csh, which
212  is copyrighted by the Regents of the University of California.]
213
214  SideEffects []
215
216******************************************************************************/
217char *
218CmdFgetsFilec(
219  char * buf,
220  int  size,
221  FILE * stream,
222  char * prompt)
223{
224  int n_read, i, len, maxlen, col, sno, modname;
225  struct tchars tchars, oldtchars;
226  DIR *dir;
227  struct dirent *dp;
228#if HAVE_LIBREADLINE
229  char *dupline;
230  char *cleanLine;
231#endif
232
233#if HAVE_TERM_INTERRUPTS
234  int omask;
235  struct sgttyb tty, oldtty;    /* To mask interuupts */
236  int pending = LPENDIN;
237#endif
238
239  char *last_word, *file, *path, *name, *line;
240  char last_char, found[MAXNAMLEN];
241  array_t *names = NIL(array_t);  /* initialize so that lint doesn't complain */
242
243  sno = fileno(stream);
244  if (sno != STDIN || !isatty(sno)){
245    if (prompt != NIL(char)){
246      (void) print_prompt(prompt);
247      (void) fflush(stdout);
248    }
249    return (fgets(buf, size, stream));
250  }
251  else if (Cmd_FlagReadByName("filec") == NIL(char)) {
252#if HAVE_LIBREADLINE
253    /* Effectively read one line of input printing the prompt */
254    dupline = (char *)readline(prompt);
255    cleanLine = removeWhiteSpaces(dupline);
256
257    /* Check if an EOF has been read */
258    if (cleanLine != NIL(char)) {
259      /* If the line is non empty, add it to the history */
260      if (*cleanLine) {
261        add_history(cleanLine);
262      }
263
264      /* Copy the contents of cleanLine to buf, to simulate fgets */
265      strncpy(buf, cleanLine, size);
266      if (strlen(cleanLine) >= size) {
267        buf[size-1] = '\0';
268      }
269      line = buf;
270    }
271    else {
272      line = NIL(char);
273    }
274    FREE(dupline);
275#else
276    /* Get rid of the trailing newline */
277    if (prompt != NIL(char)){
278      (void) print_prompt(prompt);
279      (void) fflush(stdout);
280    }
281    line = fgets(buf, size, stream);
282    if (line != NIL(char)) {
283      len = strlen(line);
284      if (len > 0 && line[len-1] == '\n') {
285        line[len-1] = '\0';
286      }
287    }
288#endif
289    return line;
290  } else {
291    if (prompt != NIL(char)){
292      (void) print_prompt(prompt);
293      (void) fflush(stdout);
294    }
295  }
296
297  /* Allow hitting ESCAPE to break a read() */
298
299  (void) ioctl(sno, TIOCGETC, (char *) &tchars);
300  oldtchars = tchars;
301  tchars.t_brkc = ESC;
302  (void) ioctl(sno, TIOCSETC, (char *) &tchars);
303
304  while ((n_read = read(sno, buf, size)) > 0) {
305    buf[n_read] = '\0';
306    last_word = &buf[n_read - 1];
307    last_char = *last_word;
308    if (last_char == '\n' || n_read == size) {
309      (void) ioctl(sno, TIOCSETC, (char *) &oldtchars);
310      *last_word = '\0';
311      return(buf);
312    }
313    if (last_char == ESC) {
314      *last_word-- = '\0';
315      (void) fprintf(stdout, "\b\b  \b\b");
316    }
317    else {
318      names = array_alloc(char *, 10);
319      (void) fputc('\n', stdout);
320    }
321    for (; last_word >= buf; --last_word) {
322      if (strchr(seperator, *last_word) != NIL(char)) {
323        break;
324      }
325    }
326    last_word++;
327    file = strrchr(buf, '/');
328    if (file == NIL(char)) {
329      file = last_word;
330      modname = 0;
331      path = ".";
332    }
333    else {
334      *file++ = '\0';
335      modname = 1;
336      path = (*last_word == '~') ? util_tilde_expand(last_word) :
337          last_word;
338    }
339    len = strlen(file);
340    dir = opendir(path);
341    if (dir == NIL(DIR) || len > MAXNAMLEN) {
342      (void) fputc(BEEP, stdout);
343    }
344    else {
345      *found = '\0';
346      maxlen = 0;
347      while ((dp = readdir(dir)) != NIL(struct dirent)) {
348        if (strncmp(file, dp->d_name, len) == 0) {
349          if (last_char == ESC) {
350            if (match(dp->d_name, found, file) == 0) {
351              break;
352            }
353          }
354          else if (len != 0 || *(dp->d_name) != '.') {
355            if (maxlen < NAMLEN(dp)) {
356              maxlen = NAMLEN(dp);
357            }
358            array_insert_last(char *, names, util_strsav(dp->d_name));
359          }
360        }
361      }
362      (void) closedir(dir);
363        if (last_char == ESC) {
364          if (*found == '\0' || strcmp(found, file) == 0) {
365            (void) fputc(BEEP, stdout);
366          }
367          else {
368            (void) strcpy(file, found);
369            (void) fprintf(stdout, "%s", &buf[n_read - 1]);
370          }
371        }
372        else {
373          maxlen += 2;
374          col = maxlen;
375          array_sort(names, cmp);
376          for (i = 0; i < array_n(names); i++) {
377            name = array_fetch(char *, names, i);
378            (void) fprintf(stdout, "%-*s", maxlen, name);
379            FREE(name);
380            col += maxlen;
381            if (col >= 80) {
382              col = maxlen;
383              (void) fputc('\n', stdout);
384            }
385          }
386          array_free(names);
387          if (col != maxlen) {
388            (void) fputc('\n', stdout);
389          }
390        }
391      }
392      (void) fflush(stdout);
393      if (modname != 0) {
394        if (path != last_word) {
395          FREE(path);
396        }
397        *--file = '/';
398      }
399
400#if HAVE_TERM_INTERRUPTS
401      /* mask interrupts temporarily */
402      omask = sigblock(sigmask(SIGINT));
403      (void) ioctl(STDOUT, TIOCGETP, (char *)&tty);
404      oldtty = tty;
405      tty.sg_flags &= ~(ECHO|CRMOD);
406      (void) ioctl(STDOUT, TIOCSETN, (char *)&tty);
407#endif
408
409      /* reprint prompt */
410      (void) write(STDOUT, "\r", 1);
411      print_prompt(prompt);
412
413      /* shove chars from buf back into the input queue */
414      for (i = 0; buf[i]; i++) {
415        (void) ioctl(STDOUT, TIOCSTI, &buf[i]);
416      }
417#if HAVE_TERM_INTERRUPTS
418      /* restore interrupts */
419      (void) ioctl(STDOUT, TIOCSETN, (char *)&oldtty);
420      (void) sigsetmask(omask);
421      (void) ioctl(STDOUT, TIOCLBIS, (char *) &pending);
422#endif
423    }
424    /* restore read() behavior */
425    (void) ioctl(sno, TIOCSETC, (char *) &oldtchars);
426    return(NIL(char));
427}
428
429#else
430
431/**Function********************************************************************
432
433  Synopsis    [required]
434
435  Description [optional]
436
437  SideEffects [required]
438
439  SeeAlso     [optional]
440
441******************************************************************************/
442char *
443CmdFgetsFilec(
444  char * buf,
445  int  size,
446  FILE * stream,
447  char * prompt)
448{
449#if HAVE_LIBREADLINE
450  char *dupline;
451  char *cleanLine;
452#endif
453  char *line;
454  int sno;
455#if !HAVE_LIBREADLINE
456  int len;
457#endif
458
459  sno = fileno(stream);
460  if (sno != STDIN || !isatty(sno)){
461    if (prompt != NIL(char)){
462      (void) print_prompt(prompt);
463      (void) fflush(stdout);
464    }
465    return (fgets(buf, size, stream));
466  } else {
467#if HAVE_LIBREADLINE
468    /* Effectively read one line of input printing the prompt */
469    dupline = (char *)readline(prompt);
470    cleanLine = removeWhiteSpaces(dupline);
471
472    /* Check if an EOF has been read */
473    if (cleanLine != NIL(char)) {
474      /* If the line is non empty, add it to the history */
475      if (*cleanLine) {
476        add_history(cleanLine);
477      }
478
479      /* Copy the contents of cleanLine to buf, to simulate fgets */
480      strncpy(buf, cleanLine, size);
481      if ((int) strlen(cleanLine) >= size) {
482        buf[size-1] = '\0';
483      }
484      line = buf;
485    }
486    else {
487      line = NIL(char);
488    }
489    FREE(dupline);
490#else
491    /* Get rid of the trailing newline */
492    if (prompt != NIL(char)){
493      (void) print_prompt(prompt);
494      (void) fflush(stdout);
495    }
496    line = fgets(buf, size, stream);
497    if (line != NIL(char)) {
498      len = strlen(line);
499      if (len > 0 && line[len-1] == '\n') {
500        line[len-1] = '\0';
501      }
502    }
503#endif
504    return line;
505  }
506
507}
508
509#endif /* HAVE_IOCTL_WITH_TIOCGETC */
510
511
512#if HAVE_IOCTL_WITH_TIOCGETC
513/**Function********************************************************************
514
515  Synopsis    [required]
516
517  Description [optional]
518
519  SideEffects [required]
520
521  SeeAlso     [optional]
522
523******************************************************************************/
524static int
525cmp(
526  const void * s1,
527  const void * s2)
528{
529    return(strcmp(*(char **)s1, *(char **)s2));
530}
531
532
533/**Function********************************************************************
534
535  Synopsis    [required]
536
537  Description [optional]
538
539  SideEffects [required]
540
541  SeeAlso     [optional]
542
543******************************************************************************/
544static int
545match(
546  char * newmatch,
547  char * lastmatch,
548  char * actual)
549{
550  int i = 0;
551
552  if (*actual == '\0' && *newmatch == '.') {
553    return(1);
554  }
555  if (*lastmatch == '\0') {
556    (void) strcpy(lastmatch, newmatch);
557    return(1);
558  }
559  while (*newmatch++ == *lastmatch) {
560    lastmatch++;
561    i++;
562  }
563  *lastmatch = '\0';
564  return(i);
565}
566/* #endif */ /* defined(hpux) */
567
568#endif
569
570
571
572/**Function********************************************************************
573
574  Synopsis    [Simple history substitution routine.]
575
576  Description [Simple history substitution routine. Not, repeat NOT, the
577  complete csh history substitution mechanism.
578
579  In the following ^ is the SUBST character and ! is the HIST character.
580  Deals with:
581        !!                      last command
582        !stuff                  last command that began with "stuff"
583        !*                      all but 0'th argument of last command
584        !$                      last argument of last command
585        !:n                     n'th argument of last command
586        !n                      repeat the n'th command
587        !-n                     repeat n'th previous command
588        ^old^new                replace "old" w/ "new" in previous command
589
590
591  Trailing spaces are significant. Removes all initial spaces.
592
593  Returns `line' if no changes were made.  Returns pointer to a static buffer
594  if any changes were made.  Sets `changed' to 1 if a history substitution
595  took place, o/w set to 0.  Returns NULL if error occurred.]
596
597  SideEffects []
598
599******************************************************************************/
600char *
601CmdHistorySubstitution(
602  char * line,
603  int * changed)
604{
605  static char buf[1024], c;
606  char *value;
607  char *last, *old, *new_, *start, *b, *l;
608  int n, len, i, num, internal_change;
609
610  *changed = 0;
611  internal_change = 0;
612  while (isspace((int)(*line))) {
613    line++;
614  }
615  if (*line == '\0') {
616    return(line);
617  }
618  n = array_n(vm_commandHistoryArray);
619  last = (n > 0) ?
620    array_fetch(char *, vm_commandHistoryArray, n - 1) : (char *) "";
621
622  b = buf;
623  if (*line == SUBST) {
624    old = line + 1;
625    new_ = strchr(old, SUBST);
626    if (new_ == NIL(char)) {
627      goto bad_modify;
628    }
629    *new_++ = '\0';                   /* makes change in contents of line */
630    start = strstr(last, old);
631    if (start == NIL(char)) {
632      *--new_ = SUBST;
633      bad_modify:
634      (void) fprintf(vis_stderr, "** cmd error: Modifier failed\n");
635      return(NIL(char));
636    }
637    while (last != start) {
638      *b++ = *last++;
639    }
640    b = do_subst(b, new_);
641    last += strlen(old);
642    while ((*b++ = *last++)) {
643    }
644    *changed = 1;
645    return(buf);
646  }
647
648  if ((value = Cmd_FlagReadByName("history_char")) != NIL(char)){
649    visHistChar = *value;
650  }
651
652  for (l = line; (*b = *l); l++) {
653    if (*l == visHistChar) {
654      /*
655       * If a \ immediately preceeds a HIST char, pass just HIST char
656       * Otherwise pass both \ and the character.
657       */
658      if (l > line && l[-1] == '\\') {
659        b[-1] = visHistChar;
660        internal_change = 1;
661        continue;
662      }
663      if (n == 0) {
664        return(bad_event(0));
665      }
666      l++;
667      /* Cannot use a switch since the history char is a variable !!! */
668      if (*l == visHistChar){
669        /* replace !! in line with last */
670        b = do_subst(b, last);
671      }
672      else if (*l == '$'){
673        /* replace !$ in line with last arg of last */
674        b = do_subst(b, getarg(last, -1));
675      }
676      else if (*l == '*'){
677        b = do_subst(b, getarg(last, -2));
678      }
679      else if (*l == ':'){
680        /* replace !:n in line with n'th arg of last */
681        l++;
682        num = getnum(&l);
683        new_ = getarg(last, num);
684        if (new_ == NIL(char)) {
685          (void) fprintf(vis_stderr, "** cmd error: Bad %c arg selector\n", visHistChar);
686          return(NIL(char));
687        }
688        b = do_subst(b, new_);
689      }
690      else if (*l == '-'){
691        /* replace !-n in line with n'th prev cmd */
692        l++;
693        num = getnum(&l);
694        if (num > n || num == 0) {
695          return(bad_event(n - num + 1));
696        }
697        b = do_subst(b, array_fetch(char *, vm_commandHistoryArray, n - num));
698      }
699      else {
700        /* replace !n in line with n'th command */
701        if (isdigit((int)(*l))) {
702          num = getnum(&l);
703          if (num > n || num == 0) {
704            return(bad_event(num));
705          }
706          b = do_subst(b, array_fetch(char *, vm_commandHistoryArray, num - 1));
707        }
708        else {  /* replace !boo w/ last cmd beginning w/ boo */
709          start = l;
710          while (*l && strchr(seperator, *l) == NIL(char)) {
711            l++;
712          }
713          c = *l;
714          *l = '\0';
715          len = strlen(start);
716          for (i = n - 1; i >= 0; i--) {
717            old = array_fetch(char *, vm_commandHistoryArray, i);
718            if (strncmp(old, start, len) == 0) {
719              b = do_subst(b, old);
720              break;
721            }
722          }
723          if (i < 0) {
724            (void) fprintf(vis_stderr, "** cmd error: Event not found: %s\n", start);
725            *l = c;
726            return(NIL(char));
727          }
728          *l-- = c;
729
730        }
731      }
732      *changed = 1;
733    }
734    else {
735      b++;
736    }
737  }
738  if (*changed != 0 || internal_change != 0) {
739    return(buf);
740  }
741  return(line);
742}
743
744
745/**Function********************************************************************
746
747  Synopsis    [required]
748
749  Description [optional]
750
751  SideEffects [required]
752
753  SeeAlso     [optional]
754
755******************************************************************************/
756static int
757getnum(
758  char ** linep)
759{
760  int num = 0;
761  char *line = *linep;
762
763  for (; isdigit((int)(*line)); line++) {
764    num *= 10;
765    num += *line - '0';
766  }
767  *linep = line - 1;
768  return(num);
769}
770
771
772/**Function********************************************************************
773
774  Synopsis    [required]
775
776  Description [optional]
777
778  SideEffects [required]
779
780  SeeAlso     [optional]
781
782******************************************************************************/
783static char *
784getarg(
785  char * line,
786  int  num)
787{
788  static char buf[128];
789  char *b, *c;
790  int i;
791
792  if (num == -1) {
793    i = 123456;
794  }
795  else if (num == -2) {
796    i = 1;
797  }
798  else {
799    i = num;
800  }
801
802  c = line;
803  do {
804    b = line = c;
805    while (*line && strchr(seperator, *line) == NIL(char)) {
806      line++;
807    }
808    c = line;
809    while (*c && strchr(seperator, *c) != NIL(char)) {
810      c++;
811    }
812    if (*c == '\0') {
813      break;
814    }
815  } while (--i >= 0);
816
817  if (i > 0) {
818    if (num == -1) {
819      return(b);
820    }
821    return(NIL(char));
822  }
823  if (num < 0) {
824    return(b);
825  }
826  c = buf;
827  do {
828    *c++ = *b++;
829  } while (b < line && c < &buf[127]);
830  *c = '\0';
831  return(buf);
832}
833
834
835/**Function********************************************************************
836
837  Synopsis    [required]
838
839  Description [optional]
840
841  SideEffects [required]
842
843  SeeAlso     [optional]
844
845******************************************************************************/
846static char *
847bad_event(
848  int  n)
849{
850  (void) fprintf(vis_stderr, "** cmd error: Event %d not found\n", n);
851  return(NIL(char));
852}
853
854
855/**Function********************************************************************
856
857  Synopsis    [required]
858
859  Description [optional]
860
861  SideEffects [required]
862
863  SeeAlso     [optional]
864
865******************************************************************************/
866static char *
867do_subst(
868  char * dest,
869  char * new_)
870{
871  while ((*dest = *new_++)) {
872    dest++;
873  }
874  return(dest);
875}
876
877
878/**Function********************************************************************
879
880  Synopsis    [required]
881
882  Description [optional]
883
884  SideEffects [required]
885
886  SeeAlso     [optional]
887
888******************************************************************************/
889static void
890print_prompt(
891  char * prompt)
892{
893  char buf[256];
894
895  if (prompt == NIL(char)) return;
896
897  while (*prompt != '\0') {
898    if (*prompt == visHistChar) {
899      (void) sprintf(buf, "%d", array_n(vm_commandHistoryArray) + 1);
900      if (write(STDOUT, buf, (int) strlen(buf)) == -1) exit(-1);
901    }
902    else {
903      if (write(STDOUT, prompt, 1) == -1) exit(-1);
904    }
905    prompt++;
906  }
907}
908
909#ifdef HAVE_LIBREADLINE
910/**Function********************************************************************
911
912  Synopsis [Removes tabs and spaces from the beginning and end of string.]
913
914  SideEffects        []
915
916******************************************************************************/
917static char *
918removeWhiteSpaces(
919  char *string)
920{
921  char *left;
922  char *right;
923
924  if (string == NIL(char)) {
925    return NIL(char);
926  }
927
928  /* Traverse the beginning of the string */
929  for (left = string; *left == ' ' || *left == '\t'; left++);
930
931  /* If we reached the end of the string */
932  if (*left == 0) {
933    return left;
934  }
935
936  /* Traverse the end of the string */
937  right = left + strlen(left) - 1;
938  while (right > left && (*right == ' ' || *right == '\t')) {
939    right--;
940  }
941  /* Set the new end of string */
942  *++right = '\0';
943
944  return left;
945} /* End of removeWhiteSpaces */
946#endif
Note: See TracBrowser for help on using the repository browser.