Merge branch 'nasm-2.12.xx' of ssh://repo.or.cz/srv/git/nasm into nasm-2.12.xx
[nasm.git] / rdoff / rdflib.c
blob06cce3c79eaaf13a2163bd1bab19c729065d57df
1 /* ----------------------------------------------------------------------- *
2 *
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"
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <errno.h>
64 #include <string.h>
65 #include <inttypes.h>
66 #include <time.h>
67 #include <inttypes.h>
69 /* functions supported:
70 * create a library (no extra operands required)
71 * add a module from a library (requires filename and name to give mod.)
72 * replace a module in a library (requires given name and filename)
73 * delete a module from a library (requires given name)
74 * extract a module from the library (requires given name and filename)
75 * list modules
78 const char *usage =
79 "usage:\n"
80 " rdflib x libname [extra operands]\n\n"
81 " where x is one of:\n"
82 " c - create library\n"
83 " a - add module (operands = filename module-name)\n"
84 " x - extract (module-name filename)\n"
85 " r - replace (module-name filename)\n"
86 " d - delete (module-name)\n" " t - list\n";
88 /* Library signature */
89 const char *rdl_signature = "RDLIB2", *sig_modname = ".sig";
91 char **_argv;
93 #define _ENDIANNESS 0 /* 0 for little, 1 for big */
95 static void int32_ttolocal(int32_t *l)
97 #if _ENDIANNESS
98 uint8_t t;
99 uint8_t *p = (uint8_t *)l;
101 t = p[0];
102 p[0] = p[3];
103 p[3] = t;
104 t = p[1];
105 p[1] = p[2];
106 p[2] = p[1];
107 #else
108 (void)l; /* placate optimizers */
109 #endif
112 static char copybytes(FILE * fp, FILE * fp2, int n)
114 int i, t = 0;
116 for (i = 0; i < n; i++) {
117 t = fgetc(fp);
118 if (t == EOF) {
119 fprintf(stderr, "rdflib: premature end of file in '%s'\n",
120 _argv[2]);
121 exit(1);
123 if (fp2)
124 if (fputc(t, fp2) == EOF) {
125 fprintf(stderr, "rdflib: write error\n");
126 exit(1);
129 return (char)t; /* return last char read */
132 static int32_t copyint32_t(FILE * fp, FILE * fp2)
134 int32_t l;
135 int i, t;
136 uint8_t *p = (uint8_t *)&l;
138 for (i = 0; i < 4; i++) { /* skip magic no */
139 t = fgetc(fp);
140 if (t == EOF) {
141 fprintf(stderr, "rdflib: premature end of file in '%s'\n",
142 _argv[2]);
143 exit(1);
145 if (fp2)
146 if (fputc(t, fp2) == EOF) {
147 fprintf(stderr, "rdflib: write error\n");
148 exit(1);
150 *p++ = t;
152 int32_ttolocal(&l);
153 return l;
156 int main(int argc, char **argv)
158 FILE *fp, *fp2 = NULL, *fptmp;
159 char *p, buf[256], c;
160 int i;
161 int32_t l;
162 time_t t;
163 char rdbuf[10];
165 _argv = argv;
167 if (argc < 3 || !strncmp(argv[1], "-h", 2)
168 || !strncmp(argv[1], "--h", 3)) {
169 fputs(usage, stdout);
170 exit(1);
173 switch (argv[1][0]) {
174 case 'c': /* create library */
175 fp = fopen(argv[2], "wb");
176 if (!fp) {
177 fprintf(stderr, "rdflib: could not open '%s'\n", argv[2]);
178 perror("rdflib");
179 exit(1);
181 fwrite(sig_modname, 1, strlen(sig_modname) + 1, fp);
182 fwrite(rdl_signature, 1, strlen(rdl_signature), fp);
183 t = time(NULL);
184 l = sizeof(t);
185 fwrite(&l, sizeof(l), 1, fp);
186 fwrite(&t, 1, l, fp);
187 fclose(fp);
188 break;
190 case 'a': /* add module */
191 if (argc < 5) {
192 fprintf(stderr, "rdflib: required parameter missing\n");
193 exit(1);
195 fp = fopen(argv[2], "ab");
196 if (!fp) {
197 fprintf(stderr, "rdflib: could not open '%s'\n", argv[2]);
198 perror("rdflib");
199 exit(1);
202 fp2 = fopen(argv[3], "rb");
203 if (!fp2) {
204 fprintf(stderr, "rdflib: could not open '%s'\n", argv[3]);
205 perror("rdflib");
206 exit(1);
209 p = argv[4];
210 do {
211 if (fputc(*p, fp) == EOF) {
212 fprintf(stderr, "rdflib: write error\n");
213 exit(1);
215 } while (*p++);
217 while (!feof(fp2)) {
218 i = fgetc(fp2);
219 if (i == EOF) {
220 break;
223 if (fputc(i, fp) == EOF) {
224 fprintf(stderr, "rdflib: write error\n");
225 exit(1);
228 fclose(fp2);
229 fclose(fp);
230 break;
232 case 'x':
233 if (argc < 5) {
234 fprintf(stderr, "rdflib: required parameter missing\n");
235 exit(1);
237 case 't':
238 fp = fopen(argv[2], "rb");
239 if (!fp) {
240 fprintf(stderr, "rdflib: could not open '%s'\n", argv[2]);
241 perror("rdflib");
242 exit(1);
245 fp2 = NULL;
246 while (!feof(fp)) {
247 /* read name */
248 p = buf;
249 while ((*(p++) = (char)fgetc(fp)))
250 if (feof(fp))
251 break;
253 if (feof(fp))
254 break;
256 fp2 = NULL;
257 if (argv[1][0] == 'x') {
258 /* check against desired name */
259 if (!strcmp(buf, argv[3])) {
260 fp2 = fopen(argv[4], "wb");
261 if (!fp2) {
262 fprintf(stderr, "rdflib: could not open '%s'\n",
263 argv[4]);
264 perror("rdflib");
265 exit(1);
268 } else
269 printf("%-40s ", buf);
271 /* step over the RDOFF file, extracting type information for
272 * the listing, and copying it if fp2 != NULL */
274 if (buf[0] == '.') {
276 if (argv[1][0] == 't')
277 for (i = 0; i < 6; i++)
278 printf("%c", copybytes(fp, fp2, 1));
279 else
280 copybytes(fp, fp2, 6);
282 l = copyint32_t(fp, fp2);
284 if (argv[1][0] == 't')
285 printf(" %"PRId32" bytes content\n", l);
287 copybytes(fp, fp2, l);
288 } else if ((c = copybytes(fp, fp2, 6)) >= '2') { /* version 2 or above */
289 l = copyint32_t(fp, fp2);
291 if (argv[1][0] == 't')
292 printf("RDOFF%c %"PRId32" bytes content\n", c, l);
293 copybytes(fp, fp2, l); /* entire object */
294 } else {
295 if (argv[1][0] == 't')
296 printf("RDOFF1\n");
298 * version 1 object, so we don't have an object content
299 * length field.
301 copybytes(fp, fp2, copyint32_t(fp, fp2)); /* header */
302 copybytes(fp, fp2, copyint32_t(fp, fp2)); /* text */
303 copybytes(fp, fp2, copyint32_t(fp, fp2)); /* data */
306 if (fp2)
307 break;
309 fclose(fp);
310 if (fp2)
311 fclose(fp2);
312 else if (argv[1][0] == 'x') {
313 fprintf(stderr, "rdflib: module '%s' not found in '%s'\n",
314 argv[3], argv[2]);
315 exit(1);
317 break;
319 case 'r': /* replace module */
320 argc--;
321 case 'd': /* delete module */
322 if (argc < 4) {
323 fprintf(stderr, "rdflib: required parameter missing\n");
324 exit(1);
327 fp = fopen(argv[2], "rb");
328 if (!fp) {
329 fprintf(stderr, "rdflib: could not open '%s'\n", argv[2]);
330 perror("rdflib");
331 exit(1);
334 if (argv[1][0] == 'r') {
335 fp2 = fopen(argv[4], "rb");
336 if (!fp2) {
337 fprintf(stderr, "rdflib: could not open '%s'\n", argv[4]);
338 perror("rdflib");
339 exit(1);
343 fptmp = tmpfile();
344 if (!fptmp) {
345 fprintf(stderr, "rdflib: could not open temporary file\n");
346 perror("rdflib");
347 exit(1);
350 /* copy library into temporary file */
351 fseek(fp, 0, SEEK_END); /* get file length */
352 l = ftell(fp);
353 fseek(fp, 0, SEEK_SET);
354 copybytes(fp, fptmp, l);
355 rewind(fptmp);
356 freopen(argv[2], "wb", fp);
358 while (!feof(fptmp)) {
359 /* read name */
360 p = buf;
361 while ((*(p++) = (char)fgetc(fptmp)))
362 if (feof(fptmp))
363 break;
365 if (feof(fptmp))
366 break;
368 /* check against desired name */
369 if (!strcmp(buf, argv[3])) {
370 fread(p = rdbuf, 1, sizeof(rdbuf), fptmp);
371 l = *(int32_t *)(p + 6);
372 fseek(fptmp, l, SEEK_CUR);
373 break;
374 } else {
375 fwrite(buf, 1, strlen(buf) + 1, fp); /* module name */
376 if ((c = copybytes(fptmp, fp, 6)) >= '2') {
377 l = copyint32_t(fptmp, fp); /* version 2 or above */
378 copybytes(fptmp, fp, l); /* entire object */
383 if (argv[1][0] == 'r') {
384 /* copy new module into library */
385 p = argv[3];
386 do {
387 if (fputc(*p, fp) == EOF) {
388 fprintf(stderr, "rdflib: write error\n");
389 exit(1);
391 } while (*p++);
393 while (!feof(fp2)) {
394 i = fgetc(fp2);
395 if (i == EOF) {
396 break;
398 if (fputc(i, fp) == EOF) {
399 fprintf(stderr, "rdflib: write error\n");
400 exit(1);
403 fclose(fp2);
406 /* copy rest of library if any */
407 while (!feof(fptmp)) {
408 i = fgetc(fptmp);
409 if (i == EOF) {
410 break;
413 if (fputc(i, fp) == EOF) {
414 fprintf(stderr, "rdflib: write error\n");
415 exit(1);
419 fclose(fp);
420 fclose(fptmp);
421 break;
423 default:
424 fprintf(stderr, "rdflib: command '%c' not recognized\n",
425 argv[1][0]);
426 exit(1);
428 return 0;