source: trunk/emx/src/emxtsf/emxtsf.c@ 3669

Last change on this file since 3669 was 936, checked in by bird, 22 years ago

Don't use EMX specific getopt when the standard one will do.

  • Property cvs2svn:cvs-rev set to 1.6
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 10.7 KB
Line 
1/* emxtsf.c -- Simplify construction of .TSF files
2 Copyright (c) 1996-1998 Eberhard Mattes
3
4This file is part of emxtsf.
5
6emxtsf is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11emxtsf is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with emxtsf; see the file COPYING. If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
20
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <getopt.h>
26#include <sys/moddef.h>
27
28
29struct sym
30{
31 struct sym *next;
32 int ord;
33 char def;
34 char *name;
35};
36
37#define HASHSIZE 997
38static struct sym *sym_hash[HASHSIZE];
39static const char *dll_name;
40static int warning_level;
41
42static void *xmalloc (size_t n)
43{
44 void *p;
45
46 p = malloc (n);
47 if (p == NULL)
48 {
49 fprintf (stderr, "Out of memory\n");
50 exit (2);
51 }
52 return p;
53}
54
55
56static void usage (void)
57{
58 fputs ("emxtsf " VERSION INNOTEK_VERSION " -- Copyright (c) 1996 by Eberhard Mattes\n\n"
59 "Usage: emxtsf [-d <dll_name>] [-w <level>] <tss_file> <map_file> <def_file>\n",
60 stderr);
61 exit (1);
62}
63
64
65static int hash (const char *name, int len)
66{
67 unsigned h;
68 int i;
69
70 h = 0;
71 for (i = 0; i < len; ++i)
72 h = (h << 2) ^ (unsigned char)name[i];
73 return h % HASHSIZE;
74}
75
76
77static struct sym *find_sym (const char *name, int len)
78{
79 struct sym *sp;
80
81 for (sp = sym_hash[hash (name, len)]; sp != NULL; sp = sp->next)
82 if (strlen (sp->name) == len && memcmp (sp->name, name, len) == 0)
83 return sp;
84 return NULL;
85}
86
87
88static void read_map (const char *fname)
89{
90 FILE *f;
91 char line[512];
92 char start;
93 unsigned seg, off;
94 int pos, i, h, len;
95 struct sym *sp;
96
97 f = fopen (fname, "r");
98 if (f == NULL)
99 {
100 perror (fname);
101 exit (2);
102 }
103 start = 0;
104 while (!start && fgets (line, sizeof (line), f) != NULL)
105 start = strcmp (line, " Address Publics by Value\n") == 0;
106 if (!start || fgets (line, sizeof (line), f) == NULL || line[0] != '\n')
107 {
108 fprintf (stderr, "%s: Publics not found\n", fname);
109 exit (2);
110 }
111
112 while (fgets (line, sizeof (line), f) != NULL && line[0] != '\n')
113 {
114 if (sscanf (line, " %x:%x %n", &seg, &off, &pos) != 2)
115 break;
116 if (strncmp (line + pos, "Imp", 3) == 0)
117 continue;
118 while (line[pos] == ' ')
119 ++pos;
120 i = pos;
121 while (line[i] != ' ' && line[i] != '\n' && line[i] != 0)
122 ++i;
123 if (i > pos && line[i] == '\n')
124 {
125 len = i - pos;
126 if (find_sym (line + pos, len) != NULL)
127 {
128 fprintf (stderr, "%s: Symbol `%.*s' multiply defined\n",
129 fname, len, line + pos);
130 exit (2);
131 }
132 h = hash (line + pos, len);
133 sp = xmalloc (sizeof (*sp));
134 sp->ord = 0;
135 sp->def = 0;
136 sp->name = xmalloc (len + 1);
137 memcpy (sp->name, line + pos, len);
138 sp->name[len] = 0;
139 sp->next = sym_hash[h];
140 sym_hash[h] = sp;
141 }
142 }
143
144 fclose (f);
145}
146
147
148static int handle_def (struct _md *md, const _md_stmt *stmt,
149 _md_token token, void *arg)
150{
151 struct sym *sp;
152 const char *name;
153
154 switch (token)
155 {
156 case _MD_EXPORTS:
157 if (stmt->export.ordinal != 0)
158 {
159 name = stmt->export.internalname;
160 if (*name == 0)
161 name = stmt->export.entryname;
162 sp = find_sym (name, strlen (name));
163 if (sp != NULL)
164 sp->ord = stmt->export.ordinal;
165 }
166 break;
167
168 case _MD_parseerror:
169 fprintf (stderr, "%s:%ld: %s\n", (char *)arg, _md_get_linenumber (md),
170 _md_errmsg (stmt->error.code));
171 exit (2);
172
173 default:
174 break;
175 }
176 return 0;
177}
178
179
180static void read_def (const char *fname)
181{
182 struct _md *md;
183
184 md = _md_open (fname);
185 if (md == NULL)
186 {
187 perror (fname);
188 exit (2);
189 }
190 _md_next_token (md);
191 _md_parse (md, handle_def, (void *)fname);
192 _md_close (md);
193}
194
195
196static const char *tss_fname;
197static int tss_lineno;
198
199static void syntax (void)
200{
201 fprintf (stderr, "%s:%d: Syntax error\n", tss_fname, tss_lineno);
202 exit (2);
203}
204
205
206static void read_tss (const char *fname)
207{
208 FILE *f;
209 char line[512], *s, c;
210 char fun[512], fun2[520];
211 char group[40], type[40], mem[128];
212 char *prefix;
213 struct sym *sp;
214 int i, j, len, off, minor, uminor;
215
216 f = fopen (fname, "r");
217 if (f == NULL)
218 {
219 perror (fname);
220 exit (2);
221 }
222
223 tss_fname = fname;
224 tss_lineno = 0;
225 group[0] = 0; type[0] = 0;
226 uminor = 0x7fff;
227 if (dll_name == NULL)
228 prefix = "";
229 else
230 {
231 prefix = xmalloc (strlen (dll_name) + 3);
232 sprintf (prefix, "%s: ", dll_name);
233 }
234
235 while (fgets (line, sizeof (line), f) != NULL)
236 {
237 ++tss_lineno;
238 s = strchr (line, '\n');
239 if (s != NULL) *s = 0;
240 if (line[0] == ';' || line[0] == 0)
241 continue;
242 if (line[1] != ' ' || line[2] == ' ')
243 syntax ();
244 if (line[0] == 'G')
245 {
246 _strncpy (group, line + 2, sizeof (group));
247 continue;
248 }
249 if (line[0] == 'T')
250 {
251 _strncpy (type, line + 2, sizeof (type));
252 continue;
253 }
254 if (group[0] == 0 || type[0] == 0)
255 syntax ();
256 i = 2;
257 while (line[i] != ' ' && line[i] != '(' && line[i] != 0)
258 ++i;
259 len = i - 2;
260 if (len >= sizeof (fun) - 1)
261 len = sizeof (fun) - 2;
262 memcpy (fun, line + 2, len);
263 fun[len] = 0;
264 sp = find_sym (fun, len);
265 if (sp == NULL)
266 {
267 fun[0] = '_';
268 memcpy (fun + 1, line + 2, len);
269 fun[++len] = 0;
270 sp = find_sym (fun, len);
271 if (sp == NULL)
272 {
273 fprintf (stderr, "%s:%d: Symbol `%s' not found\n",
274 tss_fname, tss_lineno, fun + 1);
275 continue;
276 }
277 }
278 if (sp->def)
279 {
280 fprintf (stderr, "%s:%d: Symbol `%s' multiply defined\n",
281 tss_fname, tss_lineno, fun);
282 continue;
283 }
284 sp->def = 1;
285 if (line[0] == 'I')
286 continue;
287 if (sp->ord != 0)
288 minor = sp->ord;
289 else
290 minor = uminor--;
291 while (line[i] == ' ')
292 ++i;
293 if (line[i] != '(')
294 syntax ();
295 ++i;
296 printf ("TRACE\n"
297 "MINOR=0x%.4x,\n"
298 "TP=.%s,\n"
299 "TYPE=(PRE,%s),\n"
300 "GROUP=%s,\n"
301 "DESC=\"%s%s Pre-Invocation\",\n",
302 minor, fun, type, group, prefix, fun);
303 while (line[i] == ' ')
304 ++i;
305 if (line[i] != ')')
306 {
307 off = 4;
308 for (;;)
309 {
310 c = line[i];
311 ++i;
312 if (line[i] != ' ')
313 syntax ();
314 while (line[i] == ' ')
315 ++i;
316 j = i;
317 while (line[i] != ' ' && line[i] != ',' && line[i] != ')'
318 && line[i] != 0)
319 ++i;
320 if (i == j)
321 syntax ();
322
323 printf ("FMT=\"%.*s = ", i - j, line + j);
324 switch (c)
325 {
326 case 'q':
327 fputs ("%P%Q", stdout);
328 sprintf (mem, "MEM32=(FESP+%d,D,8)", off);
329 off += 8;
330 break;
331 case 'i':
332 fputs ("%P%D", stdout);
333 sprintf (mem, "MEM32=(FESP+%d,D,4)", off);
334 off += 4;
335 break;
336 case 'p':
337 fputs ("%P%F", stdout);
338 sprintf (mem, "MEM32=(FESP+%d,D,4)", off);
339 off += 4;
340 break;
341 case 's':
342 fputs ("\\\"%P%S\\\"", stdout);
343 sprintf (mem, "ASCIIZ32=(FESP+%d,I,128)", off);
344 off += 4;
345 break;
346 default:
347 syntax ();
348 }
349 printf ("\",\n%s,\n", mem);
350 while (line[i] == ' ')
351 ++i;
352 if (line[i] == ')')
353 break;
354 if (line[i] != ',')
355 syntax ();
356 ++i;
357 while (line[i] == ' ')
358 ++i;
359 }
360 }
361 ++i;
362 while (line[i] == ' ')
363 ++i;
364 if (line[i] != 0 && line[i] != ';')
365 syntax ();
366 puts ("FMT=\"Return address = %P%F\",");
367 puts ("MEM32=(FESP+0,D,4)\n");
368 sprintf (fun2, "__POST$%s", fun);
369 sp = find_sym (fun2, strlen (fun2));
370 if (sp != NULL)
371 {
372 printf ("TRACE\n"
373 "MINOR=0x%.4x,\n"
374 "TP=.%s,\n"
375 "TYPE=(POST,%s),\n"
376 "GROUP=%s,\n"
377 "DESC=\"%s%s Post-Invocation\",\n",
378 minor + 0x8000, fun2, type, group, prefix, fun);
379 switch (line[0])
380 {
381 case 'v':
382 break;
383 case 'i':
384 puts ("FMT=\"Return value = %D\",\n"
385 "REGS=(EAX)");
386 break;
387 case 'p':
388 puts ("FMT=\"Return value = %F\",\n"
389 "REGS=(EAX)");
390 break;
391 case 'q':
392 puts ("FMT=\"Return value = %Q\",\n"
393 "REGS=(EAX,EDX)");
394 break;
395 default:
396 syntax ();
397 }
398 putchar ('\n');
399 }
400 else if (warning_level >= 2)
401 fprintf (stderr, "%s:%d: Epilogue not found for symbol `%s'\n",
402 tss_fname, tss_lineno, fun);
403 }
404 fclose (f);
405}
406
407
408static void list_untraced (void)
409{
410 int h;
411 struct sym *sp;
412
413 for (h = 0; h < HASHSIZE; ++h)
414 for (sp = sym_hash[h]; sp != NULL; sp = sp->next)
415 if (!sp->def && sp->ord != 0)
416 fprintf (stderr, "Not traced: %s\n", sp->name);
417}
418
419
420int main (int argc, char *argv[])
421{
422 int c;
423 long n;
424 char *end;
425
426 while ((c = getopt (argc, argv, "d:w:")) != -1)
427 switch (c)
428 {
429 case 'd':
430 dll_name = optarg;
431 break;
432 case 'w':
433 n = strtol (optarg, &end, 10);
434 if (end == optarg || *end != 0 || n < 0 || n > 2)
435 usage ();
436 warning_level = (int)n;
437 break;
438 default:
439 usage ();
440 }
441
442 if (argc - optind != 3)
443 usage ();
444
445 read_map (argv[optind+1]);
446 read_def (argv[optind+2]);
447 read_tss (argv[optind+0]);
448 if (warning_level >= 1)
449 list_untraced ();
450 return 0;
451}
Note: See TracBrowser for help on using the repository browser.