FreeCalypso > hg > ueda-linux
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 } |