comparison ueda/libuschem/graphsym_load.c @ 0:cd92449fdb51

initial import of ueda and ifctf-part-lib from ifctfvax CVS
author Space Falcon <falcon@ivan.Harhan.ORG>
date Mon, 20 Jul 2015 00:24:37 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:cd92449fdb51
1 /*
2 * The black magic of loading/prescanning gschem-based uschem symbols
3 */
4
5 #include <ctype.h>
6 #include <stdio.h>
7 #include <strings.h>
8 #include "graphsym.h"
9
10 extern char *malloc();
11 extern char *copystr();
12
13 #define MAXLINE 256
14
15 static struct graphsym *symstruct;
16 static FILE *inf;
17 static int lineno;
18 static struct graphsym_pindef **pintail;
19
20 read_symbol_file(gs, f)
21 struct graphsym *gs;
22 FILE *f;
23 {
24 symstruct = gs;
25 inf = f;
26 lineno = 0;
27 pintail = &gs->gs_pins;
28 mymain();
29 if (!gs->gs_npins) {
30 fprintf(stderr, "%s: symbol has no pins (invalid)\n",
31 gs->gs_pathname);
32 exit(1);
33 }
34 }
35
36 static
37 mymain()
38 {
39 char line[MAXLINE];
40 register char *cp;
41 register int c;
42
43 while (getline(line)) {
44 if (line[0] == '%') /* PS-like comments */
45 continue;
46 if (line[0] == '\0') /* allow blank lines too */
47 continue;
48 if (!isalpha(line[0])) {
49 inv: fprintf(stderr, "%s: line %d: invalid symbol data\n",
50 symstruct->gs_pathname, lineno);
51 exit(1);
52 }
53 for (cp = line; isalpha(*cp); cp++)
54 ;
55 if (!isspace(*cp))
56 goto inv;
57 *cp++ = '\0';
58 while (isspace(*cp))
59 cp++;
60 if (!strcmp(line, "PS")) {
61 if (strcmp(cp, "{"))
62 goto inv;
63 skip_ps_block();
64 continue;
65 } else if (strlen(line) != 1)
66 goto inv;
67 line[1] = ' ';
68 /* dispatch by single-char type */
69 switch (line[0]) {
70 case 'v':
71 continue; /* ignore */
72 /* simple graphics */
73 case 'L':
74 case 'B':
75 case 'V':
76 case 'A':
77 /* ignore at this stage too */
78 continue;
79 case 'P':
80 handle_pin(line, lineno);
81 continue;
82 case 'T':
83 handle_T_obj(line, lineno);
84 continue;
85 default:
86 goto inv;
87 }
88 }
89 }
90
91 static
92 handle_pin(objline, objlineno)
93 char *objline;
94 {
95 int numparams[7];
96 char junkline[MAXLINE];
97 register struct graphsym_pindef *pin;
98
99 parse_numline(objline, objlineno, numparams, 7);
100 pin = (struct graphsym_pindef *) malloc(sizeof(struct graphsym_pindef));
101 if (!pin) {
102 perror("malloc");
103 exit(1);
104 }
105 bzero(pin, sizeof(struct graphsym_pindef));
106 if (numparams[6]) {
107 pin->gspd_x = numparams[2];
108 pin->gspd_y = numparams[3];
109 } else {
110 pin->gspd_x = numparams[0];
111 pin->gspd_y = numparams[1];
112 }
113 *pintail = pin;
114 pintail = &pin->gspd_next;
115 symstruct->gs_npins++;
116 if (!getline(junkline) || strcmp(junkline, "{")) {
117 fprintf(stderr,
118 "%s: line %d: P line must be followed by '{' line\n",
119 symstruct->gs_pathname, objlineno);
120 exit(1);
121 }
122 read_pin_attrs(pin, objlineno);
123 }
124
125 static
126 read_pin_attrs(pin, objlineno)
127 struct graphsym_pindef *pin;
128 {
129 char line[MAXLINE];
130 int Tline_parsed[9];
131 register char *cp;
132
133 for (;;) {
134 if (!getline(line)) {
135 badeof: fprintf(stderr, "%s: EOF in pin attribute block\n",
136 symstruct->gs_pathname);
137 exit(1);
138 }
139 if (line[0] == '%') /* PS-like comments */
140 continue;
141 if (line[0] == '\0') /* allow blank lines too */
142 continue;
143 if (line[0] == '}')
144 return;
145 if (!isalpha(line[0])) {
146 inv: fprintf(stderr, "%s: line %d: invalid symbol data\n",
147 symstruct->gs_pathname, lineno);
148 exit(1);
149 }
150 for (cp = line; isalpha(*cp); cp++)
151 ;
152 if (!isspace(*cp))
153 goto inv;
154 *cp++ = '\0';
155 if (!strcmp(line, "attr")) {
156 while (isspace(*cp))
157 cp++;
158 handle_attr(pin, cp);
159 continue;
160 } else if (strcmp(line, "T")) {
161 fprintf(stderr,
162 "%s: line %d: wrong object type in pin attribute block\n",
163 symstruct->gs_pathname, lineno);
164 exit(1);
165 }
166 line[1] = ' ';
167 parse_numline(line, lineno, Tline_parsed, 9);
168 if (Tline_parsed[8] < 1) {
169 fprintf(stderr, "%s: line %d: T object: num_lines<1!\n",
170 symstruct->gs_pathname, lineno);
171 exit(1);
172 }
173 if (Tline_parsed[8] > 1) {
174 fprintf(stderr,
175 "%s: line %d: multiline text object in attribute block not supported\n",
176 symstruct->gs_pathname, lineno);
177 exit(1);
178 }
179 if (!getline(line))
180 goto badeof;
181 handle_attr(pin, line);
182 }
183 }
184
185 static
186 handle_attr(pin, line)
187 register struct graphsym_pindef *pin;
188 register char *line;
189 {
190 register char *cp;
191
192 cp = index(line, '=');
193 if (!cp)
194 return;
195 *cp++ = '\0';
196 if (!*cp) /* avoid null string values */
197 return;
198 if (!strcmp(line, "pinname")) {
199 if (pin->gspd_pinname) {
200 dup: fprintf(stderr,
201 "%s: line %d: duplicate %s attribute (ignored)\n",
202 symstruct->gs_pathname, lineno, line);
203 return;
204 }
205 pin->gspd_pinname = copystr(cp);
206 } else if (!strcmp(line, "pinnumber")) {
207 if (pin->gspd_pinnumber)
208 goto dup;
209 pin->gspd_pinnumber = copystr(cp);
210 if (!strcmp(cp, "%d"))
211 symstruct->gs_varpins++;
212 } else if (!strcmp(line, "forcenet")) {
213 if (pin->gspd_forcenet)
214 goto dup;
215 pin->gspd_forcenet = copystr(cp);
216 symstruct->gs_forcenets++;
217 }
218 }
219
220 static
221 handle_T_obj(objline, objlineno)
222 char *objline;
223 {
224 int numparams[9];
225 char junkline[MAXLINE];
226 register int i;
227
228 parse_numline(objline, objlineno, numparams, 9);
229 if (numparams[8] < 1) {
230 fprintf(stderr, "%s: line %d: T object: num_lines<1!\n",
231 symstruct->gs_pathname, objlineno);
232 exit(1);
233 }
234 for (i = numparams[8]; i; i--) {
235 if (!getline(junkline)) {
236 fprintf(stderr, "%s: EOF in T object\n",
237 symstruct->gs_pathname);
238 exit(1);
239 }
240 }
241 }
242
243 static
244 parse_numline(line, lineno, numarray, nfields)
245 char *line;
246 int lineno;
247 int *numarray;
248 int nfields;
249 {
250 register char *cp, *np;
251 register int i;
252
253 for (i = 0, cp = line+1; i < nfields; i++) {
254 if (!isspace(*cp)) {
255 inv: fprintf(stderr, "%s: line %d: invalid numeric line\n",
256 symstruct->gs_pathname, lineno);
257 exit(1);
258 }
259 while (isspace(*cp))
260 cp++;
261 np = cp;
262 if (*cp == '-')
263 cp++;
264 if (!isdigit(*cp))
265 goto inv;
266 while (isdigit(*cp))
267 cp++;
268 numarray[i] = atoi(np);
269 }
270 if (*cp)
271 goto inv;
272 }
273
274 static
275 getline(linebuf)
276 char *linebuf;
277 {
278 register char *cp;
279
280 if (fgets(linebuf, MAXLINE, inf) == NULL)
281 return(0);
282 lineno++;
283 /* strip trailing newline or other whitespace */
284 cp = index(linebuf, '\0');
285 while (cp > linebuf && isspace(cp[-1]))
286 cp--;
287 *cp = '\0';
288 return(1);
289 }
290
291 static
292 skip_ps_block()
293 {
294 register int c, n;
295
296 for (n = 0; n >= 0; ) {
297 c = getc(inf);
298 switch (c) {
299 case EOF:
300 badeof: fprintf(stderr, "%s: EOF in a PS block\n",
301 symstruct->gs_pathname);
302 exit(1);
303 case '%':
304 for (;;) {
305 c = getc(inf);
306 if (c == EOF)
307 goto badeof;
308 if (c == '\n')
309 break;
310 }
311 /* FALL THRU */
312 case '\n':
313 lineno++;
314 continue;
315 case '(':
316 skip_over_ps_string();
317 continue;
318 case ')':
319 fprintf(stderr,
320 "%s: line %d: unmatched \')\' in a PS block",
321 symstruct->gs_pathname, lineno);
322 exit(1);
323 case '{':
324 n++;
325 continue;
326 case '}':
327 n--;
328 continue;
329 }
330 }
331 c = getc(inf);
332 if (c != '\n') {
333 fprintf(stderr,
334 "%s: line %d: '}' closing PS block must be directly followed by newline\n",
335 symstruct->gs_pathname, lineno);
336 exit(1);
337 }
338 lineno++;
339 }
340
341 static
342 skip_over_ps_string()
343 {
344 register int c, n;
345
346 for (n = 1; n > 0; ) {
347 c = getc(inf);
348 switch (c) {
349 case EOF:
350 badeof: fprintf(stderr, "%s: EOF in a PS block\n",
351 symstruct->gs_pathname);
352 exit(1);
353 case '\n':
354 lineno++;
355 continue;
356 case '(':
357 n++;
358 continue;
359 case ')':
360 n--;
361 continue;
362 case '\\':
363 c = getc(inf);
364 if (c == EOF)
365 goto badeof;
366 if (c == '\n')
367 lineno++;
368 continue;
369 }
370 }
371 }