Jspice3
lexical.c
Go to the documentation of this file.
1 /***************************************************************************
2 JSPICE3 adaptation of Spice3e2 - Copyright (c) Stephen R. Whiteley 1992
3 Copyright 1990 Regents of the University of California. All rights reserved.
4 Authors: 1985 Wayne A. Christopher
5  1992 Stephen R. Whiteley
6 ****************************************************************************/
7 
8 /*
9  * Initial lexer.
10  */
11 
12 /***************************************************************************
13 To implement command completion under DOS, one must define TIOCSTI in
14 os_msdos.h, and add routines mygetc() and ioctl() which do the right
15 things, i.e., allow stuffing characters into the input buffer. In DOS,
16 ^A and ^Z call the abort routine in interactive mode. ^D signals command
17 match printing and can be first on a line unlike in UNIX. Beware that
18 some compilers supply an ioctl() routine which won't work here, if this
19 is the case, you may have to define ioctl to something else in os_msdos.h.
20 ****************************************************************************/
21 
22 #include "spice.h"
23 #include "cpdefs.h"
24 #include <errno.h>
25 
26 #include <sys/types.h>
27 
28 #ifdef HAVE_SGTTY_H
29 #include <sgtty.h>
30 #else
31 #ifdef HAVE_TERMIO_H
32 #include <termio.h>
33 #else
34 #ifdef HAVE_TERMIOS_H
35 #include <termios.h>
36 #endif
37 #endif
38 #endif
39 
40 #include "ftegraph.h"
41 
42 #ifdef __STDC__
43 static void prompt(void);
44 #else
45 static void prompt();
46 #endif
47 
48 FILE *cp_inp_cur = NULL;
49 int cp_event = 1;
50 bool cp_interactive = true;
51 bool cp_bqflag = false;
54 char cp_hash = '#';
55 
56 static int numeofs = 0;
57 
58 #define ESCAPE '\033'
59 
60 /* Return a list of words, with backslash quoting and '' quoting done.
61  * Strings en(void) closed in "" or `` are made single words and returned,
62  * but with the "" or `` still present. For the \ and '' cases, the
63  * 8th bit is turned on (as in csh) to prevent them from being recogized,
64  * and stripped off once all processing is done. We also have to deal with
65  * command, filename, and keyword completion here.
66  * If string is non-NULL, then use it instead of the fp. Escape and EOF
67  * have no business being in the string.
68  */
69 
70 #define newword cw->wl_word = copy(buf); \
71  cw->wl_next = alloc(struct wordlist); \
72  cw->wl_next->wl_prev = cw; \
73  cw = cw->wl_next; \
74  bzero(buf, BSIZE_SP); \
75  i = 0;
76 
77 
78 wordlist *
79 cp_lexer(string)
80 
81 char *string;
82 {
83  int c;
84  int i, j;
85  wordlist *wlist = NULL, *cw = NULL;
86  char buf[BSIZE_SP], linebuf[BSIZE_SP], d;
87 
88  if (cp_inp_cur == NULL)
89  cp_inp_cur = cp_in;
90 
91  if (!string && cp_interactive) {
92  cp_ccon(true);
93  prompt();
94  }
95 nloop:
96  i = 0;
97  j = 0;
98  bzero(linebuf, BSIZE_SP);
99  bzero(buf, BSIZE_SP);
100  wlist = cw = alloc(struct wordlist);
101  cw->wl_next = cw->wl_prev = NULL;
102  for (;;) {
103  if (string) {
104  c = *string++;
105  if (c == '\0')
106  c = '\n';
107  if (c == ESCAPE)
108  c = '[';
109  }
110  else
111  c = DevGetchar(cp_inp_cur);
112 gotchar:
113  if ((c != EOF) && (c != ESCAPE) && (c != 4)) /* SRW - 4 added */
114  linebuf[j++] = c;
115  if (c != EOF && c != 4) /* SRW - ditto */
116  numeofs = 0;
117  if (i == BSIZE_SP - 1) {
118  fprintf(cp_err, "Warning: word too long.\n");
119  c = ' ';
120  }
121  if (j == BSIZE_SP - 1) {
122  fprintf(cp_err, "Warning: line too long.\n");
123  if (cp_bqflag)
124  c = EOF;
125  else
126  c = '\n';
127  }
128  if (c != EOF)
129  c = strip(c); /* Don't need to do this really. */
130 
131  /* "backslash" quoting */
132  if (c == '\\' && DIR_TERM != '\\' || c == '\026' /* ^V */ ) {
133  c = quote(string ? *string++ : DevGetchar(cp_inp_cur));
134  linebuf[j++] = strip(c);
135  }
136 
137  if ((c == '\n') && cp_bqflag)
138  c = ' ';
139  if ((c == EOF || c == 4) && cp_bqflag) /* SRW - 4 added */
140  c = '\n';
141  if ((c == cp_hash) && !cp_interactive && (j == 1)) {
142  if (string)
143  return (NULL);
144  while (((c = DevGetchar(cp_inp_cur)) != '\n') &&
145  (c != EOF));
146  goto nloop;
147  }
148  switch (c) {
149 
150  case ' ':
151  case '\t':
152  if (i > 0) {
153  newword;
154  }
155  break;
156 
157  case '\n':
158  if (i) {
159  buf[i] = '\0';
160  cw->wl_word = copy(buf);
161  }
162  else if (cw->wl_prev) {
163  cw->wl_prev->wl_next = NULL;
164  tfree(cw);
165  }
166  else {
167  cw->wl_word = NULL;
168  }
169  goto done;
170 
171  case '\'':
172  while (((c = (string ? *string++ :
173  DevGetchar(cp_inp_cur))) != '\'')
174  && (i < BSIZE_SP - 1)) {
175  if ((c == '\n') || (c == EOF) || (c == ESCAPE))
176  goto gotchar;
177  else {
178  buf[i++] = quote(c);
179  linebuf[j++] = c;
180  }
181  }
182  linebuf[j++] = '\'';
183  break;
184 
185  case '"':
186  case '`':
187  d = c;
188  buf[i++] = d;
189  while (((c = (string ? *string++ : DevGetchar(cp_inp_cur)))
190  != d) && (i < BSIZE_SP - 2)) {
191  if ((c == '\n') || (c == EOF) || (c == ESCAPE))
192  goto gotchar;
193  else if (c == '\\') {
194  linebuf[j++] = c;
195  c = (string ? *string++ :
197  buf[i++] = quote(c);
198  linebuf[j++] = c;
199  }
200  else {
201  buf[i++] = c;
202  linebuf[j++] = c;
203  }
204  }
205  buf[i++] = d;
206  linebuf[j++] = d;
207  break;
208 
209  case EOF:
210  case 4: /* ^D */
211 
212  if (cp_interactive && !cp_nocc &&
213  (string == NULL)) {
214 #ifdef notdef
215 /* ^D logout */
216  if (j == 0) {
217  if (cp_ignoreeof && (numeofs++
218  < 23)) {
219  fputs(
220  "Use \"quit\" to quit.\n",
221  stdout);
222  }
223  else {
224  fputs("quit\n", stdout);
225  cp_doquit();
226  }
227  goto done;
228  }
229 #endif
230  cp_ccom(wlist, buf, false);
231  wl_free(wlist);
232  (void) fputc('\r', cp_out);
233  prompt();
234  for (j = 0; linebuf[j]; j++)
235 #ifdef TIOCSTI
236  /* SRW - below was cp_out, a bug */
237  (void) ioctl(fileno(cp_in), TIOCSTI,
238  linebuf + j);
239 #else
240  fputc(linebuf[j], cp_out); /* But you can't edit */
241 #endif
242  goto nloop;
243  }
244  else { /* EOF during a source */
245 
246  if (cp_interactive) {
247  fputs("quit\n", stdout);
248  cp_doquit();
249  goto done;
250  }
251  else
252  return (NULL);
253  }
254  case ESCAPE:
255  if (cp_interactive && !cp_nocc) {
256 
257  fputs("\b\b \b\b\r", cp_out);
258  prompt();
259  for (j = 0; linebuf[j]; j++)
260 #ifdef TIOCSTI
261  /* SRW - below was cp_out, a bug */
262  (void) ioctl(fileno(cp_in), TIOCSTI,
263  linebuf + j);
264 #else
265  fputc(linebuf[j], cp_out); /* But you can't edit */
266 #endif
267  cp_ccom(wlist, buf, true);
268  wl_free(wlist);
269  goto nloop;
270  } /* Else fall through */
271 
272  default:
273  /* We have to remember the special cases $<, $&, $#&, $?& */
274  if ((cp_chars[c] & CPC_BRL) && (i > 0)) {
275  switch (c) {
276 
277  case '<':
278  if (buf[i-1] == '$')
279  break;
280  { newword; }
281  break;
282 
283  case '&':
284  if (buf[i-1] == '$')
285  break;
286  if (i > 1 && (buf[i-1] == '#' || buf[i-1] == '?') &&
287  buf[i-2] == '$')
288  break;
289  { newword; }
290  break;
291 
292  default:
293  { newword; }
294  }
295  }
296 
297  buf[i++] = c;
298 
299  /* have to also catch <=, >=, and <> */
300 
301  if (cp_chars[c] & CPC_BRR) {
302  switch (c) {
303 
304  case '<':
305  if (i > 1 && buf[i-2] == '$')
306  break;
307 
308  case '>':
309  d = c;
310  if (string) {
311  c = *string++;
312  if (c == '\0')
313  c = '\n';
314  if (c == ESCAPE)
315  c = '[';
316  }
317  else
318  c = DevGetchar(cp_inp_cur);
319 
320  if (c == '=' || (d == '<' && c == '>')) {
321  buf[i++] = c;
322  linebuf[j++] = c;
323  { newword; }
324  break;
325  }
326  { newword; }
327  goto gotchar;
328 
329  case '&':
330  if (i > 1 && buf[i-2] == '$')
331  break;
332  if (i > 2 && (buf[i-2] == '#' || buf[i-2] == '?') &&
333  buf[i-3] == '$')
334  break;
335  { newword; }
336  break;
337 
338  default:
339  { newword; }
340  }
341  }
342  }
343  }
344 done:
345  return (wlist);
346 }
347 
348 
349 static void
351 {
352  char *s;
353 
354  if (cp_interactive == false)
355  return;
356  if (cp_promptstring == NULL)
357  s = "-> ";
358  else
359  s = cp_promptstring;
360  if (cp_altprompt)
361  s = cp_altprompt;
362 
363  while (*s) {
364  switch (strip(*s)) {
365  case '!':
366  fprintf(cp_out, "%d", cp_event);
367  break;
368  case '\\':
369  if (*(s + 1))
370  (void) putc(strip(*++s), cp_out);
371 
372  /* SRW -p prints cwd */
373  case '-':
374  if (*(s+1) == 'p') {
375  char *c, *getcwd();
376  (void) fprintf(cp_out,"%s",c = getcwd(NULL,128));
377  tfree(c);
378  s++;
379  break;
380  }
381  default:
382  (void) putc(strip(*s), cp_out);
383  }
384  s++;
385  }
386  (void) fflush(cp_out);
387  return;
388 }
static char buf[MAXPROMPT]
Definition: arg.c:18
#define BSIZE_SP
Definition: misc.h:19
#define quote(c)
Definition: cpdefs.h:74
#define strip(c)
Definition: cpdefs.h:75
char cp_chars[]
Definition: cshpar.c:79
Definition: cddefs.h:119
static void prompt()
Definition: lexical.c:350
#define ESCAPE
Definition: lexical.c:58
#define CPC_BRL
Definition: cpdefs.h:67
bool cp_ignoreeof
Definition: variable.c:49
#define alloc(type)
Definition: cdmacs.h:21
int bzero(char *ptr, int num)
Definition: string.c:357
char * getcwd(char *buf, int size)
Definition: libfuncs.c:124
char * copy()
void wl_free()
FILE * cp_err
Definition: help.c:101
FILE * cp_inp_cur
Definition: lexical.c:48
bool cp_interactive
Definition: lexical.c:50
Definition: cddefs.h:237
#define tfree(x)
Definition: cdmacs.h:22
int cp_event
Definition: lexical.c:49
#define NULL
Definition: spdefs.h:121
FILE * cp_out
Definition: help.c:101
void cp_doquit()
Definition: cpitf.c:329
char * cp_altprompt
Definition: lexical.c:53
static double c
Definition: vectors.c:16
static int numeofs
Definition: lexical.c:56
#define CPC_BRR
Definition: cpdefs.h:66
Definition: cpstd.h:21
int DevGetchar()
char * cp_promptstring
Definition: lexical.c:52
bool cp_nocc
Definition: complete.c:75
bool cp_bqflag
Definition: lexical.c:51
#define newword
Definition: lexical.c:70
wordlist * cp_lexer(char *string)
Definition: lexical.c:79
FILE * cp_in
Definition: help.c:101
char cp_hash
Definition: lexical.c:54
void cp_ccom()
void cp_ccon()