Jspice3
mfbcaps.c
Go to the documentation of this file.
1 /**********
2 Copyright 1990 Regents of the University of California. All rights reserved.
3 Author: -C- 1982 Giles Billingsley
4 **********/
5 /*
6  * mfbcaps.c
7  *
8  * sccsid "@(#)mfbcaps.c 1.9 9/3/83"
9  *
10  * MFB is a graphics package that was developed by the integrated
11  * circuits group of the Electronics Research Laboratory and the
12  * Department of Electrical Engineering and Computer Sciences at
13  * the University of California, Berkeley, California. The programs
14  * in MFB are available free of charge to any interested party.
15  * The sale, resale, or use of these program for profit without the
16  * express written consent of the Department of Electrical Engineering
17  * and Computer Sciences, University of California, Berkeley, California,
18  * is forbidden.
19  */
20 
21 
22 
23 #define MAXHOP 5 /* max number of MCE=indirections */
24 #define BADNUM 0 /* illegal number for numeric capability */
25 
26 #include "spice.h"
27 #include "mfb.h"
28 #include <ctype.h>
29 #include <string.h>
30 
31 
32 /*
33  * mfbcap - routines for dealing with the terminal capability data base
34  * mfbcap routines must be loaded
35  *
36  * Essentially all the work here is scanning and decoding escapes
37  * in string capabilities. We don't use stdio because the editor
38  * doesn't, and because living w/o it is not hard.
39  */
40 
41 static char *mfb_buf;
42 static int hopcount; /* detect infinite loops in mfbcap, init 0 */
43 
44 char *MFBGetStr();
45 int MFBGetNum();
46 int MFBGetFlag();
47 int MFBGetEnt();
48 int MFBCheckForMCE();
49 
50 static char *MFBSkip();
51 static char *MFBCapDecod();
52 
53 /*
54  * Get an entry for terminal name in buffer bp,
55  * from the mfbcap file. Parse is very rudimentary;
56  * we just notice escaped newlines.
57  */
58 int
59 MFBGetEnt(bp, name, mfbcapFile)
60 char *bp;
61 char *name;
62 char *mfbcapFile;
63 {
64  register char *cp;
65  register int c;
66  register int i = 0, cnt = 0;
67  register int NewLine;
68  char inputBuffer[BUFSIZE];
69  FILE *CapFile;
70  int mfbcapDesc;
71 
72  hopcount = 0; /* Fixes bug in in spice3a* -- could only plot 5 times. */
73  mfb_buf = bp;
74  if((CapFile = fopen(mfbcapFile, "r")) == NULL)
75  return(MFBBADMCF);
76  mfbcapDesc = fileno(CapFile);
77 
78  /*
79  * It should be faster to read mfbcap by 4Kbytes at a time
80  */
81  for(;;){
82  NewLine = 0;
83  cp = bp;
84  for(;;){
85  if(i >= cnt){
86  cnt = read(mfbcapDesc, inputBuffer, BUFSIZE);
87  if(cnt <= 0 && !NewLine){
88  if(close(mfbcapDesc) < 0)
89  return(MFBBADMCF);
90  }
91  i = 0;
92  }
93  c = inputBuffer[i++];
94 
95  /*
96  * Check for continuation from previous line
97  */
98  if(NewLine && c != ' ' && c != '\t'){
99  --i;
100  break;
101  }
102  /*
103  * Check for new line
104  */
105  NewLine = 0;
106  if(c == '\n'){
107  NewLine = 1;
108  continue;
109  }
110  /*
111  * Check for line too long
112  */
113  else if(cp >= bp + BUFSIZE){
114  return(MFBMCELNG);
115  }
116  else
117  *cp++ = c;
118  }
119  *cp = 0;
120 
121  /*
122  * The real work for the match.
123  */
124  if(mfbnamatch(name)){
125  if(close(mfbcapDesc) < 0)
126  return(MFBBADMCF);
127  return( MFBCheckForMCE(mfbcapFile) );
128  }
129  }
130 }
131 
132 
133 /*
134  * check the last entry, see if it's MCE=xxxxx. If so,
135  * recursively find xxxxx and append that entry (minus the names)
136  * to take the place of the MCE=xxxxx entry. This allows mfbcap
137  * entries to say "like an AED but with a graphics tablet".
138  * Note that this works because of the left to right scan.
139  */
140 int
141 MFBCheckForMCE(mfbcapFile)
142 char *mfbcapFile;
143 {
144  register char *p, *q;
145  char mfbname[16]; /* name of similar terminal */
146  char mfbbuf[BUFSIZE];
147  char *holdgbuf = mfb_buf;
148  int l;
149 
150  p = mfb_buf + strlen(mfb_buf);
151  for(l=0; l<2; ++l){
152  while(*--p != ','){
153  if(p < mfb_buf){
154  return(MFBBADMCE);
155  }
156  }
157  }
158  while(*p == ',' || *p == ' ' || *p == '\t')
159  p++;
160 
161  /* p now points to beginning of last field */
162  if(p[0] != 'M' || p[1] != 'C' || p[2] != 'E') return(MFBOK);
163  (void) strcpy(mfbname,p+4);
164  q = mfbname;
165  while(q && *q != ',')
166  q++;
167  *q = 0;
168  if(++hopcount > MAXHOP){
169  return(MFBINFMCE);
170  }
171  if((l = MFBGetEnt(mfbbuf,mfbname,mfbcapFile)) != 1){
172  return(l);
173  }
174  for(q=mfbbuf; *q != ','; q++) ;
175  l = p - holdgbuf + strlen(q);
176  if(l > BUFSIZE){
177  q[BUFSIZE - (p-mfb_buf)] = 0;
178  return(MFBMCELNG);
179  }
180  (void) strcpy(p, q+1);
181  mfb_buf = holdgbuf;
182  return(MFBOK);
183 }
184 
185 
186 /*
187  * mfbnamatch deals with name matching. The first field of the mfbcap
188  * entry is a sequence of names separated by |'s, so we compare
189  * against each such name. The normal , terminator after the last
190  * name (before the first field) stops us.
191  */
193 char *np;
194 {
195  register char *Np, *Bp;
196 
197  Bp = mfb_buf;
198  if(*Bp == '#') return(FALSE);
199  for(;;){
200  for(Np = np; *Np && *Bp == *Np; Bp++, Np++) continue;
201  if(*Np == 0 && (*Bp == '|' || *Bp == ',' || *Bp == 0))
202  return(TRUE);
203  while(*Bp && *Bp != ',' && *Bp != '|') Bp++;
204  if(*Bp == 0 || *Bp == ',') return(FALSE);
205  Bp++;
206  }
207 }
208 
209 
210 
211 /*
212  * Skip to the next field.
213  */
214 static char *
216 char *bp;
217 {
218  while(*bp && !(*bp == ',' && *(bp - 1) != '\\'))
219  bp++;
220 
221  /* Now clear the white space */
222  while(*bp == ',' || *bp == ' ' || *bp == '\t')
223  bp++;
224  return(bp);
225 }
226 
227 
228 
229 /*
230  * Handle a flag option.
231  * Flag options are given "naked", i.e. followed by a , or the end
232  * of the buffer. Return 1 if we find the option, or 0 if it is
233  * not given.
234  */
236 char *id;
237 {
238  register char *bp = mfb_buf;
239  register char *cp;
240  register int i;
241 
242  for(;;){
243  bp = MFBSkip(bp);
244  if(!*bp) return(0);
245  i = 0;
246  cp = id;
247  while(*cp != 0 && *bp != 0){
248  if(*cp++ != *bp++){
249  i = 1;
250  break;
251  }
252  }
253  if(!i){
254  if(!*bp || *bp == ',')
255  return(1);
256  else if(*bp == '@')
257  return(0);
258  }
259  }
260 }
261 
262 
263 
264 /*
265  * Get a string valued option.
266  * These are given as
267  * GIS=\E\E\027
268  * Much decoding is done on the strings, and the strings are
269  * placed in area, which is a ref parameter which is updated.
270  * For speed there is no checking on area overflow.
271  */
272 char *
273 MFBGetStr(id, area)
274 char *id, **area;
275 {
276  register char *bp = mfb_buf;
277  register char *cp;
278  register int i;
279 
280  for(;;){
281  bp = MFBSkip(bp);
282  if(!*bp) return(NULL);
283  i = 0;
284  cp = id;
285  while(*cp != 0 && *bp != 0){
286  if(*cp++ != *bp++){
287  i = 1;
288  break;
289  }
290  }
291  if(i || *bp != '=') continue;
292  bp++;
293  return(MFBCapDecod(bp, area));
294  }
295 }
296 
297 
298 
299 /*
300  * MFBCapDecod decodes the string capability escapes.
301  */
302 static char *
303 MFBCapDecod(str, area)
304 char *str;
305 char **area;
306 {
307  char *cp;
308  int c;
309  char *dp;
310  int i;
311 
312  cp = *area;
313  while((c = *str++) && c != ','){
314  switch (c){
315  case '^':
316  c = *str++ & 037;
317  break;
318 
319  case '\\':
320  dp = "E\033^^\\\\,,n\nr\rt\tb\bf\f";
321  c = *str++;
322  nextc:
323  if(*dp++ == c){
324  c = *dp++;
325  break;
326  }
327  dp++;
328  if(*dp)
329  goto nextc;
330  if(isdigit(c)){
331  c -= '0', i = 2;
332  do
333  c <<= 3, c |= *str++ - '0';
334  while(--i && isdigit(*str));
335  }
336  break;
337  }
338  *cp++ = c;
339  }
340  *cp++ = 0;
341  str = *area;
342  *area = cp;
343  return(str);
344 }
345 
346 
347 
348 /*
349  * Return the (numeric) option id.
350  * Numeric options look like
351  * MCL#255
352  * i.e. the option string is separated from the numeric value by
353  * a # character. If the option is not found we return -1.
354  * Note that we handle hex numbers beginning with "0x" or "0X",
355  * and octal numbers beginning with 0.
356  *
357  */
359 char *id;
360 {
361  register int i, j;
362  register char *bp = mfb_buf;
363  register char negative = 0 ;
364  register char *cp;
365 
366  for(;;){
367  bp = MFBSkip(bp);
368  if(*bp == 0) return(BADNUM);
369  i = 0;
370  cp = id;
371  while(*cp != 0 && *bp != 0){
372  if(*cp++ != *bp++){
373  i = 1;
374  break;
375  }
376  }
377  if(*bp == 0) return(BADNUM);
378  if(i || *bp != '#') continue;
379  bp++;
380  if((negative=(*bp == '-'))) bp++ ;
381  i = 0;
382  while( (j = ((int)(*bp) - 060)) >= 0 && (j < 10) ) {
383  bp++; i *= 10; i += j;
384  }
385  if(negative)
386  return(-i) ;
387  else
388  return(i);
389  }
390 }
391 
char * name
Definition: inpptree.h:151
#define FALSE
Definition: mfb.h:23
#define MFBBADMCF
Definition: mfb.h:493
#define BADNUM
Definition: mfbcaps.c:24
int MFBGetEnt()
int MFBGetFlag()
char * strcpy()
#define MFBOK
Definition: mfb.h:491
FILE * p
Definition: proc2mod.c:48
Definition: cddefs.h:312
#define TRUE
Definition: util.h:27
static int hopcount
Definition: mfbcaps.c:42
#define NULL
Definition: spdefs.h:121
int MFBGetNum()
char * MFBGetStr()
static double c
Definition: vectors.c:16
static char * MFBSkip()
#define MAXHOP
Definition: mfbcaps.c:23
#define MFBBADMCE
Definition: mfb.h:495
#define MFBINFMCE
Definition: mfb.h:496
#define BUFSIZE
Definition: mfb.h:29
int MFBCheckForMCE()
mfbnamatch(char *np)
Definition: mfbcaps.c:192
#define MFBMCELNG
Definition: mfb.h:494
static char * MFBCapDecod()
static char * mfb_buf
Definition: mfbcaps.c:41