9
|
1 /*
|
|
2 * This module provides library functions for reading and parsing
|
|
3 * netlist files in our unet format.
|
|
4 */
|
|
5
|
|
6 #include <stdio.h>
|
|
7 #include <stdlib.h>
|
|
8 #include <ctype.h>
|
|
9 #include <string.h>
|
|
10 #include <strings.h>
|
|
11 #include "unetrd.h"
|
|
12
|
|
13 open_unet_input_file(filename, state)
|
|
14 char *filename;
|
|
15 struct unetrd_state *state;
|
|
16 {
|
|
17 state->filename = filename;
|
|
18 state->stream = fopen(filename, "r");
|
|
19 if (!state->stream) {
|
|
20 perror(filename);
|
|
21 exit(1);
|
|
22 }
|
|
23 state->lineno = 0;
|
|
24 }
|
|
25
|
|
26 static void
|
|
27 handle_name_only(state, out, rest)
|
|
28 struct unetrd_state *state;
|
|
29 struct unetrd_out *out;
|
|
30 char *rest;
|
|
31 {
|
|
32 char *cp;
|
|
33
|
|
34 for (cp = rest; isspace(cp); cp++)
|
|
35 ;
|
|
36 if (*cp == '\0' || *cp == '#') {
|
|
37 fprintf(stderr, "%s line %d: a name is expected after %s\n",
|
|
38 state->filename, state->lineno, out->keyword);
|
|
39 exit(1);
|
|
40 }
|
|
41 out->objname = cp;
|
|
42 while (*cp && !isspace(*cp))
|
|
43 cp++;
|
|
44 if (*cp)
|
|
45 *cp++ = '\0';
|
|
46 while (isspace(*cp))
|
|
47 cp++;
|
|
48 if (*cp && *cp != '#') {
|
|
49 fprintf(stderr,
|
|
50 "%s line %d: unexpected extra fields on %s line\n",
|
|
51 state->filename, state->lineno, out->keyword);
|
|
52 exit(1);
|
|
53 }
|
|
54 }
|
|
55
|
|
56 static void
|
|
57 handle_component_opening(state, out, rest)
|
|
58 struct unetrd_state *state;
|
|
59 struct unetrd_out *out;
|
|
60 char *rest;
|
|
61 {
|
|
62 char *cp;
|
|
63
|
|
64 for (cp = rest; isspace(cp); cp++)
|
|
65 ;
|
|
66 if (*cp == '\0' || *cp == '#') {
|
|
67 fprintf(stderr, "%s line %d: a name is expected after %s\n",
|
|
68 state->filename, state->lineno, out->keyword);
|
|
69 exit(1);
|
|
70 }
|
|
71 out->objname = cp;
|
|
72 while (*cp && !isspace(*cp))
|
|
73 cp++;
|
|
74 if (*cp)
|
|
75 *cp++ = '\0';
|
|
76 while (isspace(*cp))
|
|
77 cp++;
|
|
78 if (*cp != '{') {
|
|
79 fprintf(stderr,
|
|
80 "%s line %d: expected '{' at the end of %s line\n",
|
|
81 state->filename, state->lineno, out->keyword);
|
|
82 exit(1);
|
|
83 }
|
|
84 }
|
|
85
|
|
86 static void
|
|
87 handle_pin_line(state, out, rest)
|
|
88 struct unetrd_state *state;
|
|
89 struct unetrd_out *out;
|
|
90 char *rest;
|
|
91 {
|
|
92 char *cp = rest, *fields[3];
|
|
93 int i;
|
|
94
|
|
95 for (i = 0; i < 3; i++) {
|
|
96 while (isspace(*cp))
|
|
97 cp++;
|
|
98 if (*cp == '\0' || *cp == '#') {
|
|
99 error: fprintf(stderr,
|
|
100 "%s line %d: invalid syntax on %s line\n",
|
|
101 state->filename, state->lineno, out->keyword);
|
|
102 exit(1);
|
|
103 }
|
|
104 fields[i] = cp;
|
|
105 while (*cp && !isspace(*cp))
|
|
106 cp++;
|
|
107 if (*cp)
|
|
108 *cp++ = '\0';
|
|
109 }
|
|
110 out->objname = fields[0];
|
|
111 if (strcmp(fields[1], "="))
|
|
112 goto error;
|
|
113 if (!strcmp(fields[2], "NET")) {
|
|
114 while (isspace(*cp))
|
|
115 cp++;
|
|
116 if (*cp == '\0' || *cp == '#')
|
|
117 goto error;
|
|
118 out->connect_to_net = cp;
|
|
119 while (*cp && !isspace(*cp))
|
|
120 cp++;
|
|
121 if (*cp)
|
|
122 *cp++ = '\0';
|
|
123 } else if (!strcmp(fields[2], "NC")) {
|
|
124 out->connect_to_net = 0;
|
|
125 while (isspace(*cp))
|
|
126 cp++;
|
|
127 if (*cp++ != '(')
|
|
128 goto error;
|
|
129 out->nc_comment = cp;
|
|
130 while (*cp && *cp != ')')
|
|
131 cp++;
|
|
132 if (*cp != ')')
|
|
133 goto error;
|
|
134 *cp++ = '\0';
|
|
135 } else
|
|
136 goto error;
|
|
137 while (isspace(*cp))
|
|
138 cp++;
|
|
139 if (*cp && *cp != '#') {
|
|
140 fprintf(stderr,
|
|
141 "%s line %d: unexpected extra fields on %s line\n",
|
|
142 state->filename, state->lineno, out->keyword);
|
|
143 exit(1);
|
|
144 }
|
|
145 }
|
|
146
|
|
147 static struct objmap {
|
|
148 char *keyword;
|
|
149 int typecode;
|
|
150 void (*handler)();
|
|
151 } objmap[] = {
|
|
152 {"}", UNETOBJ_CLOSINGBRACE, 0},
|
|
153 {"NET", UNETOBJ_NET, handle_name_only},
|
|
154 {"COMPONENT", UNETOBJ_COMPONENT, handle_component_opening},
|
|
155 {"STARPOINT", UNETOBJ_STARPOINT, handle_component_opening},
|
|
156 {"PRIMITIVE", UNETOBJ_PRIMITIVE, handle_name_only},
|
|
157 {"ALTNAME", UNETOBJ_ALTNAME, handle_name_only},
|
|
158 {"PIN", UNETOBJ_PIN, handle_pin_line},
|
|
159 {"PINMAP", UNETOBJ_PINMAP, handle_pin_line},
|
|
160 {0, 0, 0}
|
|
161 };
|
|
162
|
|
163 read_unet_line(state, out)
|
|
164 struct unetrd_state *state;
|
|
165 struct unetrd_out *out;
|
|
166 {
|
|
167 static char linebuf[256];
|
|
168 char *cp;
|
|
169 struct objmap *tp;
|
|
170
|
|
171 /* read lines until we get a non-empty, non-comment line or EOF */
|
|
172 for (;;) {
|
|
173 if (!fgets(linebuf, sizeof linebuf, state->stream))
|
|
174 return(0);
|
|
175 state->lineno++;
|
|
176 cp = index(linebuf, '\n');
|
|
177 if (!cp) {
|
|
178 fprintf(stderr,
|
|
179 "error: %s line %d is too long or unterminated\n",
|
|
180 state->filename, state->lineno);
|
|
181 exit(1);
|
|
182 }
|
|
183 *cp = '\0';
|
|
184 for (cp = linebuf; isspace(*cp); cp++)
|
|
185 ;
|
|
186 if (*cp && *cp != '#')
|
|
187 break;
|
|
188 }
|
|
189 out->keyword = cp;
|
|
190 while (*cp && !isspace(*cp))
|
|
191 cp++;
|
|
192 if (*cp)
|
|
193 *cp++ = '\0';
|
|
194 for (tp = objmap; tp->keyword; tp++)
|
|
195 if (!strcmp(tp->keyword, out->keyword))
|
|
196 break;
|
|
197 if (!tp->keyword) {
|
|
198 fprintf(stderr, "%s line %d: object type \"%s\" unknown\n",
|
|
199 state->filename, state->lineno, out->keyword);
|
|
200 exit(1);
|
|
201 }
|
|
202 out->typecode = tp->typecode;
|
|
203 if (tp->handler)
|
|
204 tp->handler(state, out, cp);
|
|
205 return(1);
|
|
206 }
|