source: trunk/emx/src/emxomf/emxomfar.c@ 3669

Last change on this file since 3669 was 566, checked in by zap, 22 years ago

Fixed conflicts.

  • Property cvs2svn:cvs-rev set to 1.7
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 11.7 KB
Line 
1/* emxomfar.c -- Manage OMF libraries (.LIB files)
2 Copyright (c) 1992-1998 Eberhard Mattes
3
4This file is part of emxomfar.
5
6emxomfar 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
11emxomfar 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 emxomfar; 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 <io.h>
26#include <sys/types.h>
27#include <sys/stat.h>
28#include <sys/omflib.h>
29
30
31#define FALSE 0
32#define TRUE 1
33
34/* The name of the original library file. */
35static char *lib_fname;
36
37/* The name of the new library file. */
38static char *new_fname;
39
40/* This is the command character. */
41static char cmd;
42
43/* This flag is non-zero if the v option is given. */
44static char verbose;
45
46/* This flag is non-zero if the c option is given. */
47static char silent;
48
49/* OMFLIB descriptor of the original library. */
50static struct omflib *lib;
51
52/* OMFLIB descriptor of the new library. */
53static struct omflib *new_lib;
54
55
56/* Tell the user how to run this program. */
57
58static void usage (void)
59{
60 fprintf (stderr, "emxomfar " VERSION INNOTEK_VERSION " -- "
61 "Copyright (c) 1992-1996 by Eberhard Mattes\n\n");
62 fprintf (stderr, "Usage: emxomfar [-p#] <command> <library_file> [<module>]...\n");
63 fprintf (stderr, "\nCommands:\n");
64 fprintf (stderr, " d delete module from library\n");
65 fprintf (stderr, " r replace modules in library\n");
66 fprintf (stderr, " t list table of contents\n");
67 fprintf (stderr, " x extract modules from library\n");
68 fprintf (stderr, "\nOptions (append to command):\n");
69 fprintf (stderr, " c no warning when creating new library\n");
70 fprintf (stderr, " v verbose output\n");
71 fprintf (stderr, "\nOptions (prededing command):\n");
72 fprintf (stderr, " -p# set page size\n");
73 exit (1);
74}
75
76
77/* This function is passed to omflib_pubdef_walk to list the public
78 symbols. */
79
80static int list_pubdef (const char *name, char *error)
81{
82 printf (" %s\n", name);
83 return 0;
84}
85
86
87/* Perform the requested action for the module NAME. */
88
89static void do_mod (const char *name)
90{
91 char error[512], c;
92 char mod_name[256];
93 int page;
94
95 c = 'a'; page = 0;
96 omflib_module_name (mod_name, name);
97 if (lib != NULL)
98 {
99 page = omflib_find_module (lib, name, error);
100 if (cmd == 'r')
101 {
102 if (page != 0)
103 {
104 c = 'r';
105 if (omflib_mark_deleted (lib, name, error) != 0)
106 {
107 fprintf (stderr, "emxomfar: %s\n", error);
108 exit (2);
109 }
110 }
111 }
112 else if (page == 0)
113 {
114 fprintf (stderr, "emxomfar: Module not found: %s\n", name);
115 return;
116 }
117 }
118 switch (cmd)
119 {
120 case 't':
121 if (verbose)
122 {
123 printf("%s (page %d):\n", mod_name, page);
124 if (omflib_pubdef_walk (lib, page, list_pubdef, error) != 0)
125 fprintf (stderr, "emxomfar: %s\n", error);
126 fputchar ('\n');
127 }
128 else
129 printf ("%s\n", mod_name);
130 break;
131 case 'x':
132 if (verbose)
133 printf ("x - %s\n", name);
134 if (omflib_extract (lib, name, error) != 0)
135 {
136 fprintf (stderr, "emxomfar: %s\n", error);
137 exit (2);
138 }
139 break;
140 case 'r':
141 if (verbose)
142 printf ("%c - %s\n", c, name);
143 if (omflib_add_module (new_lib, name, error) != 0)
144 {
145 fprintf (stderr, "emxomfar: %s(%s): %s\n", new_fname, name, error);
146 exit (2);
147 }
148 break;
149 case 'd':
150 if (verbose)
151 printf ("d - %s\n", mod_name);
152 if (omflib_mark_deleted (lib, name, error) != 0)
153 fprintf (stderr, "emxomfar: %s\n", error);
154 break;
155 }
156}
157
158
159
160/**
161 * Calculate the expected page size for a library based on the
162 * parameters which is specified.
163 *
164 * @returns
165 * @param papszFiles Pointer to a vector of files.
166 * @param chCmd The command we're processing.
167 * @remark Only applies when creating a new library.
168 */
169static int calc_pagesize(char **papszFiles, const char chCmd)
170{
171 unsigned cFiles;
172 size_t cbFiles;
173 int cbPage;
174 int i;
175
176 /* if it's not a replace command return default size. */
177 if (chCmd != 'r')
178 return 16;
179
180 /*
181 * Count the files and sum their sizes.
182 */
183 for (i = 0, cFiles = 0, cbFiles = 0; papszFiles[i]; i++)
184 {
185 struct stat s;
186 cFiles++;
187 if (!stat(papszFiles[i], &s))
188 cbFiles += s.st_size;
189 else
190 cbFiles += 128 * 1024; /* file not found? just guess a size, 128kb. */
191 }
192
193 /*
194 * We'll need an approximation of this formula:
195 * cbPage = (cbPage * cFiles + cbFiles) / 65535;
196 *
197 * Let's do the calculation assuming cbPage being 256.
198 * We'll also add a few files (just for case that any of these were a library),
199 * and a couple extra of bytes too.
200 */
201 cbFiles += cFiles * 4096;
202 cFiles += 64;
203 cbPage = (256 * cFiles + cbFiles) / 65536;
204 for (i = 16; i < cbPage; )
205 i <<= 1;
206
207 if (verbose)
208 printf("calculated page size %d\n", i);
209 return i;
210}
211
212/* Cleanup, for atexit. */
213
214static void cleanup (void)
215{
216 char error[512];
217
218 if (new_fname != NULL)
219 {
220 if (new_lib != NULL)
221 {
222 omflib_close (new_lib, error);
223 new_lib = NULL;
224 }
225 if (lib != NULL)
226 {
227 omflib_close (lib, error);
228 lib = NULL;
229 }
230 remove (new_fname);
231 if (lib_fname != NULL)
232 rename (lib_fname, new_fname);
233 new_fname = NULL;
234 }
235}
236
237
238/* Entrypoint. Parse the command line, open files and perform the
239 requested action. */
240
241int main (int argc, char *argv[])
242{
243 char error[512], name[257], *s, new_cmd;
244 int page;
245 int i, n, create, page_size;
246 char ext_fname[512];
247 char bak_fname[512];
248
249 /* Expand response files and wildcards on th command line. */
250
251 _response (&argc, &argv);
252 _wildcard (&argc, &argv);
253
254 /* The default page size was 16, now we'll calculate one with
255 a minimum of 16. */
256
257 page_size = 0;
258
259 /* Parse the command line. First, check for an -p# option. */
260
261 i = 1;
262 if (i < argc && argv[i][0] == '-')
263 {
264 s = argv[i]+1;
265 switch (*s)
266 {
267 case 'p':
268 ++s;
269 page_size = strtol (s, &s, 10);
270 if (page_size < 1 || *s != 0)
271 usage ();
272 ++i;
273 break;
274 default:
275 usage ();
276 }
277 }
278
279 /* At least 2 arguments must be given: the command and the library
280 name. */
281
282 if (argc - i < 2)
283 usage ();
284
285 /* Set initial values. */
286
287 verbose = FALSE; silent = FALSE; cmd = 0;
288
289 /* Skip a leading - character, it's optional. */
290
291 s = argv[i++];
292 if (*s == '-')
293 ++s;
294
295 /* Parse the command. */
296
297 while (*s != 0)
298 {
299 new_cmd = 0;
300 switch (*s)
301 {
302 case 'v':
303 verbose = TRUE;
304 break;
305 case 'c':
306 silent = TRUE;
307 break;
308 case 's':
309 if (cmd == 0)
310 new_cmd = 's';
311 break;
312 case 'd':
313 case 'r':
314 case 't':
315 case 'x':
316 new_cmd = *s;
317 break;
318 case 'q':
319 new_cmd = 'r';
320 break;
321 case 'u':
322 if (cmd == 0)
323 new_cmd = 'r';
324 break;
325 case 'l':
326 case 'o':
327 break;
328 default:
329 usage ();
330 }
331 ++s;
332 if (new_cmd != 0)
333 {
334 if (cmd != 0)
335 usage ();
336 cmd = new_cmd;
337 }
338 }
339
340 /* Complain if no command letter was given. */
341
342 if (cmd == 0)
343 usage ();
344
345 /* The s command is a no-op. */
346
347 if (cmd == 's')
348 return 0;
349
350 /* Add the .lib default extension to the library name. The result
351 is in ext_fname. */
352
353 _strncpy (ext_fname, argv[i++], sizeof (ext_fname) - 4);
354 _defext (ext_fname, "lib");
355
356 /* Initialize file names and OMFLIB descriptors. */
357
358 lib_fname = ext_fname;
359 lib = NULL;
360 new_fname = NULL;
361 new_lib = NULL;
362
363 /* Make create non-zero iff we have to create a new library file. */
364
365 create = (cmd == 'r' && access (lib_fname, 4) != 0);
366
367 /* The r and d commands create a library file if it doesn't exist.
368 If it does exist, a backup file is created. */
369
370 if (cmd == 'r' || cmd == 'd')
371 {
372 if (create)
373 {
374 if (!silent)
375 printf ("Creating library file `%s'\n", lib_fname);
376 new_fname = lib_fname;
377 lib_fname = NULL;
378 }
379 else
380 {
381 _strncpy (bak_fname, lib_fname, sizeof (bak_fname) - 4);
382 _remext (bak_fname);
383 _defext (bak_fname, "bak");
384 if (stricmp (lib_fname, bak_fname) == 0)
385 {
386 fprintf (stderr, "Cannot update backup file\n");
387 exit (1);
388 }
389 remove (bak_fname);
390 if (rename (lib_fname, bak_fname) != 0)
391 {
392 perror (lib_fname);
393 exit (2);
394 }
395 new_fname = lib_fname;
396 lib_fname = bak_fname;
397 }
398 }
399
400 /* If no new library file is to be created, the library file is
401 supposed to exist. Open it. */
402
403 if (!create)
404 {
405 lib = omflib_open (lib_fname, error);
406 if (lib == NULL)
407 {
408 fprintf (stderr, "emxomfar: %s: %s\n", lib_fname, error);
409 exit (2);
410 }
411 }
412
413 /* Create the output library for the r and d commands. */
414
415 if (cmd == 'r' || cmd == 'd')
416 {
417 if (page_size <= 0)
418 page_size = calc_pagesize(&argv[i], cmd);
419 new_lib = omflib_create (new_fname, page_size, error);
420 if (new_lib == NULL)
421 {
422 fprintf (stderr, "emxomfar: %s: %s\n", new_fname, error);
423 exit (2);
424 }
425 }
426
427 /* Close files when done or when aborting. */
428
429 atexit (cleanup);
430
431 /* Write header of new library. */
432
433 if (cmd == 'r' || cmd == 'd')
434 {
435 if (omflib_header (new_lib, error) != 0)
436 {
437 fprintf (stderr, "emxomfar: %s\n", error);
438 exit (2);
439 }
440 }
441
442 if (i >= argc && !(cmd == 'r' || cmd == 'd'))
443 {
444
445 /* No arguments specified for the t and x commands: Apply
446 do_mod() to all modules of the library. */
447
448 n = omflib_module_count (lib, error);
449 if (n == -1)
450 {
451 fprintf (stderr, "emxomfar: %s\n", error);
452 exit (2);
453 }
454 for (i = 0; i < n; ++i)
455 {
456 if (omflib_module_info (lib, i, name, &page, error) != 0)
457 fprintf (stderr, "emxomfar: %s\n", error);
458 else
459 do_mod (name);
460 }
461 }
462 else
463 {
464 /* Apply do_mod() to all modules given on the command line. */
465
466 while (i < argc)
467 {
468 if (!(cmd == 'd' && strcmp (argv[i], "__.SYMDEF") == 0))
469 do_mod (argv[i]);
470 ++i;
471 }
472 }
473
474 /* Copy all the unmodified modules of the original library to the
475 new library. */
476
477 if (cmd == 'r' || cmd == 'd')
478 {
479 if ((!create && omflib_copy_lib (new_lib, lib, error) != 0)
480 || omflib_finish (new_lib, error) != 0
481 || omflib_close (new_lib, error) != 0)
482 {
483 fprintf (stderr, "emxomfar: %s\n", error);
484 exit (2);
485 }
486 new_lib = NULL; new_fname = NULL;
487 }
488
489 /* Close the source library. */
490
491 if (lib != NULL && omflib_close (lib, error) != 0)
492 fprintf (stderr, "emxomfar: %s\n", error);
493 return 0;
494}
Note: See TracBrowser for help on using the repository browser.