Jspice3
mfbgnc.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 C. Billingsley
4 **********/
5 /*
6  * mfbgncode.c
7  *
8  * sccsid "@(#)mfbgncode.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 #include "spice.h"
23 #include "mfb.h"
24 
25 
26 /*
27  * This routine perform graphics conversion of data as specified by
28  * a mfbcap entry pointed to by 'PM'.
29  * 'PM' is a string containing printf type escapes to allow
30  * graphics coordinate conversion. The converted data is stored in a
31  * character buffer called 'result', and a pointer to 'result' is returned.
32  *
33  * The following escapes are defined for substituting x/y coordinates:
34  *
35  * %X the X coordinate
36  * %Y the Y coordinate
37  * %Z the Z coordinate
38  * %T the T coordinate
39  * %C the C Parameter
40  * %F the F Parameter
41  * %L the L Parameter
42  *
43  * The codes below affect the state but don't use up a value.
44  *
45  * %c gives %c hacking special case characters
46  * %d as in printf
47  * %2 like %2d
48  * %3 like %3d
49  * %h1 gives one ASCII hex of low order four bits
50  * %h2 gives two ASCII hex of low order eight bits
51  * %h3 gives three ASCII hex of low order twelve bits
52  * %h4 gives four ASCII hex of low order sixteen bits
53  * %o1 gives one ASCII octal of low order three bits
54  * %o2 gives two ASCII octal of low order six bits
55  * %o3 gives three ASCII octal of low order nine bits
56  * %o4 gives four ASCII octal of low order twelve bits
57  * %o5 gives five ASCII octal of low order fifteen bits
58  * %o6 gives six ASCII octal of low order sixteen bits
59  * %t1 gives X and Y in Tektronix format with coordinate compression
60  * %t2 gives Z and T in Tektronix format with coordinate compression
61  * %t3 gives X and R in Tektronix format with coordinate compression
62  * %t4 gives R and Y in Tektronix format with coordinate compression
63  * %t5 gives R and r in Tektronix format with coordinate compression
64  * %ti gives value in Tektronix integer format
65  * %tr gives value in Tektronix real format
66  * %@ gives a NULL character
67  * %R store value in temporary buffer 1
68  * %r store value in temporary buffer 2
69  * %+x add x to the value
70  * %-x subtract x from the value
71  * %*x multiply value by x
72  * %/x divide value by x
73  * %>>x shift value right by x bits
74  * %<<x shift value left by x bits
75  * %|x OR value with x
76  * %&x AND value with x
77  * %^x XOR value with x
78  * %=x set value equal to x
79  * %ax set value equal to absolute value of x
80  * %~ complement value (1's complement)
81  * %% gives %
82  * %B BCD (2 decimal digits encoded in one byte)
83  * %D Delta Data (backwards bcd)
84  *
85  *
86  * where x can be:
87  *
88  * (1) one byte: the numberic value of this byte is used as x.
89  *
90  * (2) '#' followed by a decimal number: the decimal value is used.
91  *
92  * (3) '%' followed by C, F, L, X, Y, Z, T, r, or R: the C, F, L, X, Y, Z,
93  * T, r or R value is used.
94  *
95  * all other characters are ``self-inserting''.
96  */
97 
98 void
100 char *PM;
101 {
102 #ifdef HAVE_FTIME
103  struct timeb time1, time2;
104  float reftime, elapsedtime;
105 #endif
106  static char result[512]; /* 512 chars maximum per transfer */
107  char hexadec(); /* return a hexadecimal character */
108  char octal(); /* return an octal character */
109  char *strcpy();
110  char *cp;
111  register char *dp;
112  register int c;
113  register int which = 0;
114  register int reg=0, Reg=0;
115  int i,x1,y1;
116  int tmp,lo1,hi1,hi2;
117  int exponent;
118  int hiy,hix,loy,lox,extra,ohiy,ohix,oloy,oextra;
119  int mfbnumarg();
120 
121  cp = PM;
122  dp = result;
123  if (cp == NULL) {
124  return;
125  }
126  while (c = *cp++) {
127  if(c == '$') {
128  if(*cp != '<'){
129  *dp++ = c;
130  }
131  else{
132  ++cp;
133  *dp='\0';
134  i = dp - result;
135  /* Output the guts of the string. */
136  if (i != 0) {
137  (*MFBCurrent->outstr)(result,i);
138  }
139  /* Flush the buffer */
140  MFBUpdate();
141  /* generate the delay */
142  mfbarg(cp, Reg, reg, tmp);
143  if(*cp++ != '>')
144  continue;
145 #ifdef HAVE_FTIME
146  ftime(&time1);
147  reftime = (float)(time1.time * 1000 + time1.millitm);
148  while(tmp > 0){
149  ftime(&time2);
150  elapsedtime = (float)(time2.time * 1000 + time2.millitm)
151  - reftime;
152  if(elapsedtime > (float)tmp)
153  break;
154  }
155 #else
156  sleep((tmp + 999) / 1000);
157  /* Yuk; have to round up to seconds */
158 #endif
159  dp = result;
160  }
161  continue;
162  }
163  else if (c != '%') {
164  *dp++ = c;
165  continue;
166  }
167  switch (*cp++) {
168 
169  case 'X':
170  which = MFBCurrent->X;
171  continue;
172 
173  case 'Y':
174  which = MFBCurrent->Y;
175  continue;
176 
177  case 'Z':
178  which = MFBCurrent->Z;
179  continue;
180 
181  case 'T':
182  which = MFBCurrent->T;
183  continue;
184 
185  case 'R':
186  Reg = which;
187  continue;
188 
189  case 'r':
190  reg = which;
191  continue;
192 
193  case 'C':
194  which = MFBCurrent->fgColorId;
195  continue;
196 
197  case 'F':
198  which = MFBCurrent->fillPattern;
199  continue;
200 
201  case 'L':
202  which = MFBCurrent->lineStyle;
203  continue;
204 
205  case 'd':
206  (void) sprintf(dp,"%d",which);
207  while(*dp != 0) ++dp;
208  which = 0;
209  continue;
210 
211  case '3':
212  *dp++ = (which / 100) + '0';
213  which %= 100;
214  /* fall into... */
215 
216  case '2':
217  *dp++ = (which / 10) + '0';
218  *dp++ = (which % 10) + '0';
219  which=0;
220  continue;
221 
222  case 'h':
223  if (*cp >= '1' && *cp <= '4') {
224  for (i = *cp++ - '1'; i >= 0; i--){
225  *dp++ = hexadec(which>>(i*4));
226  }
227  which=0;
228  }
229  continue;
230 
231  case 'o':
232  if (*cp >= '1' && *cp <= '6') {
233  for (i = *cp++ - '1'; i >= 0; i--){
234  *dp++ = octal(which>>(i*3));
235  }
236  which=0;
237  }
238  continue;
239 
240  case 't': /* TEKTRONIX TERMINALS */
241  if(*cp == 'i' || *cp == 'r'){
242  tmp = which;
243  if (tmp < 0) tmp = -tmp;
244  if(*cp == 'r'){
245  exponent = 0;
246  while(tmp > 32767){
247  tmp /= 2;
248  ++exponent;
249  }
250  }
251  hi1 = tmp/16;
252  if(which < 0)
253  lo1 = tmp - hi1 * 16 + 32;
254  else
255  lo1 = tmp - hi1 * 16 + 48;
256  tmp = hi1;
257  if (tmp > 64) {
258  hi1 = tmp/64;
259  hi2 = tmp - hi1 * 64 + 64;
260  *dp++ = hi1 + 64;
261  *dp++ = hi2;
262  }
263  else if (tmp)
264  *dp++ = tmp + 64;
265  *dp++ = lo1;
266  if(*cp == 'r'){
267  /* exponent is always non-negative */
268  hi1 = exponent/16;
269  lo1 = exponent - hi1 * 16 + 48;
270  exponent = hi1;
271  if (exponent > 64) {
272  hi1 = exponent/64;
273  hi2 = exponent - hi1 * 64 + 64;
274  *dp++ = hi1 + 64;
275  *dp++ = hi2;
276  }
277  else if (exponent)
278  *dp++ = exponent + 64;
279  *dp++ = lo1;
280  }
281  }
282  else{
283  if(*cp == '1'){
284  x1 = MFBCurrent->X;
285  y1 = MFBCurrent->Y;
286  }
287  else if(*cp == '2'){
288  x1 = MFBCurrent->Z;
289  y1 = MFBCurrent->T;
290  }
291  else if(*cp == '3'){
292  x1 = MFBCurrent->X;
293  y1 = Reg;
294  }
295  else if(*cp == '4'){
296  x1 = Reg;
297  y1 = MFBCurrent->Y;
298  }
299  else if(*cp == '5'){
300  x1 = Reg;
301  y1 = reg;
302  }
303  else
304  return;
305  hiy = (y1 >> 7) & 037;
306  extra = x1 & 03 | ((y1 & 03) << 2);
307  loy = (y1 >> 2) & 037;
308  hix = (x1 >> 7) & 037;
309  lox = (x1 >> 2) & 037;
310  ohiy = (MFBCurrent->lastY >> 7) & 037;
311  oextra = MFBCurrent->lastX & 03 | ((MFBCurrent->lastY & 3)<<2);
312  oloy = (MFBCurrent->lastY >> 2) & 037;
313  ohix = (MFBCurrent->lastX >> 7) & 037;
314  MFBCurrent->lastX = x1;
315  MFBCurrent->lastY = y1;
316  if(hiy != ohiy)
317  *dp++ = hiy | 040;
318  if(hix != ohix){
319  if(extra != oextra){
320  *dp++ = extra | 0140;
321  }
322  *dp++ = loy | 0140;
323  *dp++ = hix | 040;
324  }
325  else{
326  if(extra != oextra){
327  *dp++ = extra | 0140;
328  *dp++ = loy | 0140;
329  }
330  else if(loy != oloy){
331  *dp++ = loy | 0140;
332  }
333  }
334  *dp++ = lox | 0100;
335  }
336  cp++;
337  continue;
338 
339  case '>':
340  if (*cp++ == '>'){
341  mfbarg(cp, Reg, reg, c);
342  which >>= c;
343  }
344  else {
345  cp--;
346  *dp++ = '>';
347  }
348  continue;
349 
350  case '<':
351  if (*cp++ == '<'){
352  mfbarg(cp, Reg, reg, c);
353  which <<= c;
354  }
355  else {
356  cp--;
357  *dp++ = '<';
358  }
359  continue;
360 
361  case '|':
362  mfbarg(cp, Reg, reg, c);
363  which |= c;
364  continue;
365 
366  case '&':
367  mfbarg(cp, Reg, reg, c);
368  which &= c;
369  continue;
370 
371  case '^':
372  mfbarg(cp, Reg, reg, c);
373  which ^= c;
374  continue;
375 
376  case '~':
377  which = ~which;
378  continue;
379 
380  case '-':
381  mfbarg(cp, Reg, reg, c);
382  which -= c;
383  continue;
384 
385  case '+':
386  mfbarg(cp, Reg, reg, c);
387  which += c;
388  continue;
389 
390  case '*':
391  mfbarg(cp, Reg, reg, c);
392  which *= c;
393  continue;
394 
395  case '/':
396  mfbarg(cp, Reg, reg, c);
397  which /= c;
398  continue;
399 
400  case 'c':
401  *dp++ = (char)which;
402  which = 0;
403  continue;
404 
405  case '@':
406  *dp++ = 0;
407  continue;
408 
409  case 'a':
410  which = abs(which);
411  continue;
412 
413  case '=':
414  mfbarg(cp, Reg, reg, c);
415  which = c;
416  continue;
417 
418  case '%':
419  *dp++ = c;
420  continue;
421 
422  case 'B':
423  which = (which/10 << 4) + which%10;
424  continue;
425 
426  case 'D':
427  which = which - 2 * (which%16);
428  continue;
429 
430  default:
431  return;
432  }
433  }
434  *dp='\0';
435  i = dp - result;
436 
437  /*
438  * Output the guts of the string.
439  */
440  if (i != 0) {
441  (*MFBCurrent->outstr)(result,i);
442  }
443 }
444 
445 
446 
447 char hexadec(num)
448 /* return a hexadecimal character corresponding to the
449 low order 4 bits of the argument */
450 int num;
451 {
452  num &= 0xf;
453  if(num <= 9)
454  return('0'+num);
455  else
456  return('A'+num-10);
457 }
458 
459 
460 
461 
462 char octal(num)
463 /* return an octal character corresponding to the low
464  order 3 bits of the argument */
465 int num;
466 {
467  num &= 07;
468  return('0' + num);
469 }
int lineStyle
Definition: mfb.h:269
int(* outstr)()
Definition: mfb.h:300
char * strcpy()
int T
Definition: mfb.h:222
int fgColorId
Definition: mfb.h:267
#define mfbarg(cp, Reg, reg, val)
Definition: mfb.h:398
int Y
Definition: mfb.h:222
int lastX
Definition: mfb.h:221
int Z
Definition: mfb.h:222
#define NULL
Definition: spdefs.h:121
int lastY
Definition: mfb.h:221
int fillPattern
Definition: mfb.h:268
static double c
Definition: vectors.c:16
MFB * MFBCurrent
Definition: mfbopen.c:13
void MFBGenCode(char *PM)
Definition: mfbgnc.c:99
char octal(int num)
Definition: mfbgnc.c:462
int X
Definition: mfb.h:222
char hexadec(int num)
Definition: mfbgnc.c:447
int MFBUpdate()
Definition: mfbopen.c:252