outmacho: clean up list walks, use nasm_basename/nasm_dirname
[nasm.git] / rdoff / rdflib.c
blobee7f19f6f038d3d208f0e8b497ab17bb09443f9d
1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2009 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
9 * conditions are met:
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * ----------------------------------------------------------------------- */
34 /* rdflib - manipulate RDOFF library files (.rdl) */
37 * an rdoff library is simply a sequence of RDOFF object files, each
38 * preceded by the name of the module, an ASCII string of up to 255
39 * characters, terminated by a zero.
41 * When a library is being created, special signature block is placed
42 * in the beginning of the file. It is a string 'RDLIB' followed by a
43 * version number, then int32_t content size and a int32_t time stamp.
44 * The module name of the signature block is '.sig'.
47 * There may be an optional directory placed on the end of the file.
48 * The format of the directory will be 'RDLDD' followed by a version
49 * number, followed by the length of the directory, and then the
50 * directory, the format of which has not yet been designed.
51 * The module name of the directory must be '.dir'.
53 * All module names beginning with '.' are reserved for possible future
54 * extensions. The linker ignores all such modules, assuming they have
55 * the format of a six uint8_t type & version identifier followed by int32_t
56 * content size, followed by data.
59 #include "compiler.h"
60 #include "rdfutils.h"
62 #include <stdio.h>
63 #include <stdlib.h>
64 #include <errno.h>
65 #include <string.h>
66 #include <time.h>
68 /* functions supported:
69 * create a library (no extra operands required)
70 * add a module from a library (requires filename and name to give mod.)
71 * replace a module in a library (requires given name and filename)
72 * delete a module from a library (requires given name)
73 * extract a module from the library (requires given name and filename)
74 * list modules
77 const char *usage =
78 "usage:\n"
79 " rdflib x libname [extra operands]\n\n"
80 " where x is one of:\n"
81 " c - create library\n"
82 " a - add module (operands = filename module-name)\n"
83 " x - extract (module-name filename)\n"
84 " r - replace (module-name filename)\n"
85 " d - delete (module-name)\n" " t - list\n";
87 /* Library signature */
88 const char *rdl_signature = "RDLIB2", *sig_modname = ".sig";
90 char **_argv;
92 #define _ENDIANNESS 0 /* 0 for little, 1 for big */
94 static void int32_ttolocal(int32_t *l)
96 #if _ENDIANNESS
97 uint8_t t;
98 uint8_t *p = (uint8_t *)l;
100 t = p[0];
101 p[0] = p[3];
102 p[3] = t;
103 t = p[1];
104 p[1] = p[2];
105 p[2] = p[1];
106 #else
107 (void)l; /* placate optimizers */
108 #endif
111 static char copybytes(FILE * fp, FILE * fp2, int n)
113 int i, t = 0;
115 for (i = 0; i < n; i++) {
116 t = fgetc(fp);
117 if (t == EOF) {
118 fprintf(stderr, "rdflib: premature end of file in '%s'\n",
119 _argv[2]);
120 exit(1);
122 if (fp2)
123 if (fputc(t, fp2) == EOF) {
124 fprintf(stderr, "rdflib: write error\n");
125 exit(1);
128 return (char)t; /* return last char read */
131 static int32_t copyint32_t(FILE * fp, FILE * fp2)
133 int32_t l;
134 int i, t;
135 uint8_t *p = (uint8_t *)&l;
137 for (i = 0; i < 4; i++) { /* skip magic no */
138 t = fgetc(fp);
139 if (t == EOF) {
140 fprintf(stderr, "rdflib: premature end of file in '%s'\n",
141 _argv[2]);
142 exit(1);
144 if (fp2)
145 if (fputc(t, fp2) == EOF) {
146 fprintf(stderr, "rdflib: write error\n");
147 exit(1);
149 *p++ = t;
151 int32_ttolocal(&l);
152 return l;
155 int main(int argc, char **argv)
157 FILE *fp, *fp2 = NULL, *fptmp;
158 char *p, buf[256], c;
159 int i;
160 int32_t l;
161 time_t t;
162 char rdbuf[10];
164 _argv = argv;
166 if (argc < 3 || !strncmp(argv[1], "-h", 2)
167 || !strncmp(argv[1], "--h", 3)) {
168 fputs(usage, stdout);
169 exit(1);
172 rdoff_init();
174 switch (argv[1][0]) {
175 case 'c': /* create library */
176 fp = fopen(argv[2], "wb");
177 if (!fp) {
178 fprintf(stderr, "rdflib: could not open '%s'\n", argv[2]);
179 perror("rdflib");
180 exit(1);
182 nasm_write(sig_modname, strlen(sig_modname) + 1, fp);
183 nasm_write(rdl_signature, strlen(rdl_signature), fp);
184 t = time(NULL);
185 fwriteint32_t(t, fp);
186 fclose(fp);
187 break;
189 case 'a': /* add module */
190 if (argc < 5) {
191 fprintf(stderr, "rdflib: required parameter missing\n");
192 exit(1);
194 fp = fopen(argv[2], "ab");
195 if (!fp) {
196 fprintf(stderr, "rdflib: could not open '%s'\n", argv[2]);
197 perror("rdflib");
198 exit(1);
201 fp2 = fopen(argv[3], "rb");
202 if (!fp2) {
203 fprintf(stderr, "rdflib: could not open '%s'\n", argv[3]);
204 perror("rdflib");
205 exit(1);
208 p = argv[4];
209 do {
210 if (fputc(*p, fp) == EOF) {
211 fprintf(stderr, "rdflib: write error\n");
212 exit(1);
214 } while (*p++);
216 while (!feof(fp2)) {
217 i = fgetc(fp2);
218 if (i == EOF) {
219 break;
222 if (fputc(i, fp) == EOF) {
223 fprintf(stderr, "rdflib: write error\n");
224 exit(1);
227 fclose(fp2);
228 fclose(fp);
229 break;
231 case 'x':
232 if (argc < 5) {
233 fprintf(stderr, "rdflib: required parameter missing\n");
234 exit(1);
236 case 't':
237 fp = fopen(argv[2], "rb");
238 if (!fp) {
239 fprintf(stderr, "rdflib: could not open '%s'\n", argv[2]);
240 perror("rdflib");
241 exit(1);
244 fp2 = NULL;
245 while (!feof(fp)) {
246 /* read name */
247 p = buf;
248 while ((*(p++) = (char)fgetc(fp)))
249 if (feof(fp))
250 break;
252 if (feof(fp))
253 break;
255 fp2 = NULL;
256 if (argv[1][0] == 'x') {
257 /* check against desired name */
258 if (!strcmp(buf, argv[3])) {
259 fp2 = fopen(argv[4], "wb");
260 if (!fp2) {
261 fprintf(stderr, "rdflib: could not open '%s'\n",
262 argv[4]);
263 perror("rdflib");
264 exit(1);
267 } else
268 printf("%-40s ", buf);
270 /* step over the RDOFF file, extracting type information for
271 * the listing, and copying it if fp2 != NULL */
273 if (buf[0] == '.') {
275 if (argv[1][0] == 't')
276 for (i = 0; i < 6; i++)
277 printf("%c", copybytes(fp, fp2, 1));
278 else
279 copybytes(fp, fp2, 6);
281 l = copyint32_t(fp, fp2);
283 if (argv[1][0] == 't')
284 printf(" %"PRId32" bytes content\n", l);
286 copybytes(fp, fp2, l);
287 } else if ((c = copybytes(fp, fp2, 6)) >= '2') { /* version 2 or above */
288 l = copyint32_t(fp, fp2);
290 if (argv[1][0] == 't')
291 printf("RDOFF%c %"PRId32" bytes content\n", c, l);
292 copybytes(fp, fp2, l); /* entire object */
293 } else {
294 if (argv[1][0] == 't')
295 printf("RDOFF1\n");
297 * version 1 object, so we don't have an object content
298 * length field.
300 copybytes(fp, fp2, copyint32_t(fp, fp2)); /* header */
301 copybytes(fp, fp2, copyint32_t(fp, fp2)); /* text */
302 copybytes(fp, fp2, copyint32_t(fp, fp2)); /* data */
305 if (fp2)
306 break;
308 fclose(fp);
309 if (fp2)
310 fclose(fp2);
311 else if (argv[1][0] == 'x') {
312 fprintf(stderr, "rdflib: module '%s' not found in '%s'\n",
313 argv[3], argv[2]);
314 exit(1);
316 break;
318 case 'r': /* replace module */
319 argc--;
320 case 'd': /* delete module */
321 if (argc < 4) {
322 fprintf(stderr, "rdflib: required parameter missing\n");
323 exit(1);
326 fp = fopen(argv[2], "rb");
327 if (!fp) {
328 fprintf(stderr, "rdflib: could not open '%s'\n", argv[2]);
329 perror("rdflib");
330 exit(1);
333 if (argv[1][0] == 'r') {
334 fp2 = fopen(argv[4], "rb");
335 if (!fp2) {
336 fprintf(stderr, "rdflib: could not open '%s'\n", argv[4]);
337 perror("rdflib");
338 exit(1);
342 fptmp = tmpfile();
343 if (!fptmp) {
344 fprintf(stderr, "rdflib: could not open temporary file\n");
345 perror("rdflib");
346 exit(1);
349 /* copy library into temporary file */
350 fseek(fp, 0, SEEK_END); /* get file length */
351 l = ftell(fp);
352 fseek(fp, 0, SEEK_SET);
353 copybytes(fp, fptmp, l);
354 rewind(fptmp);
355 if (freopen(argv[2], "wb", fp) == NULL) {
356 fprintf(stderr, "rdflib: could not reopen '%s'\n", argv[2]);
357 perror("rdflib");
358 exit(1);
361 while (!feof(fptmp)) {
362 /* read name */
363 p = buf;
364 while ((*(p++) = (char)fgetc(fptmp)))
365 if (feof(fptmp))
366 break;
368 if (feof(fptmp))
369 break;
371 /* check against desired name */
372 if (!strcmp(buf, argv[3])) {
373 if (fread(p = rdbuf, 1, sizeof(rdbuf), fptmp) < 10) {
374 nasm_fatal(0, "short read on input");
376 l = *(int32_t *)(p + 6);
377 fseek(fptmp, l, SEEK_CUR);
378 break;
379 } else {
380 nasm_write(buf, strlen(buf) + 1, fp); /* module name */
381 if ((c = copybytes(fptmp, fp, 6)) >= '2') {
382 l = copyint32_t(fptmp, fp); /* version 2 or above */
383 copybytes(fptmp, fp, l); /* entire object */
388 if (argv[1][0] == 'r') {
389 /* copy new module into library */
390 p = argv[3];
391 do {
392 if (fputc(*p, fp) == EOF) {
393 fprintf(stderr, "rdflib: write error\n");
394 exit(1);
396 } while (*p++);
398 while (!feof(fp2)) {
399 i = fgetc(fp2);
400 if (i == EOF) {
401 break;
403 if (fputc(i, fp) == EOF) {
404 fprintf(stderr, "rdflib: write error\n");
405 exit(1);
408 fclose(fp2);
411 /* copy rest of library if any */
412 while (!feof(fptmp)) {
413 i = fgetc(fptmp);
414 if (i == EOF) {
415 break;
418 if (fputc(i, fp) == EOF) {
419 fprintf(stderr, "rdflib: write error\n");
420 exit(1);
424 fclose(fp);
425 fclose(fptmp);
426 break;
428 default:
429 fprintf(stderr, "rdflib: command '%c' not recognized\n",
430 argv[1][0]);
431 exit(1);
433 return 0;