# HG changeset patch
# User lost
# Date 1237704708 0
# Node ID bb2665c7005c25be6dd8e69ed6a95d64df5defaa
# Parent 857cb407229e4a7889fc804b1ba168d7f67ca143
Added --extract and --replace to lwar
diff -r 857cb407229e -r bb2665c7005c ChangeLog
--- a/ChangeLog Sun Mar 22 04:24:39 2009 +0000
+++ b/ChangeLog Sun Mar 22 06:51:48 2009 +0000
@@ -18,6 +18,8 @@
LWLINK (they get prepended to the built in link script)
[+] added ability to output a "linkmap" to lwlink (--map, -m)
[+] added LWEX0 (LWOS simple binary) target to LWLINK
+[+] added ability to extract files in LWAR
+[+] added ability to "replace" members in LWAR
[b] arranged for output files for lwasm/lwlink to be removed if the assembly
or linking fails
[ ] DECB output of LWLINK now collapses contiguous output blocks into single
diff -r 857cb407229e -r bb2665c7005c lwar/Makefile.am
--- a/lwar/Makefile.am Sun Mar 22 04:24:39 2009 +0000
+++ b/lwar/Makefile.am Sun Mar 22 06:51:48 2009 +0000
@@ -1,3 +1,3 @@
bin_PROGRAMS = lwar
-lwar_SOURCES = main.c util.c lwar.c list.c add.c remove.c
+lwar_SOURCES = main.c util.c lwar.c list.c add.c remove.c replace.c extract.c
EXTRA_DIST = lwar.h util.h
diff -r 857cb407229e -r bb2665c7005c lwar/extract.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lwar/extract.c Sun Mar 22 06:51:48 2009 +0000
@@ -0,0 +1,125 @@
+/*
+extract.c
+Copyright © 2009 William Astle
+
+This file is part of LWAR.
+
+LWAR is free software: you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation, either version 3 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+more details.
+
+You should have received a copy of the GNU General Public License along with
+this program. If not, see .
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include
+#include
+#include
+#include
+
+#include "lwar.h"
+
+void do_extract(void)
+{
+ FILE *f;
+ char buf[8];
+ long l;
+ int c;
+ char fnbuf[1024];
+ int i;
+ FILE *nf;
+
+ f = fopen(archive_file, "r");
+ if (!f)
+ {
+ perror("Opening archive file");
+ exit(1);
+ }
+
+ fread(buf, 1, 6, f);
+ if (memcmp("LWAR1V", buf, 6))
+ {
+ fprintf(stderr, "%s is not a valid archive file.\n", archive_file);
+ exit(1);
+ }
+
+ for (;;)
+ {
+ c = fgetc(f);
+ if (ferror(f))
+ {
+ perror("Reading archive file");
+ exit(1);
+ }
+ if (c == EOF)
+ return;
+
+
+ // find the end of the file name
+ if (!c)
+ return;
+
+ i = 0;
+ while (c)
+ {
+ fnbuf[i++] = c;
+ c = fgetc(f);
+ if (c == EOF || ferror(f))
+ {
+ fprintf(stderr, "Bad archive file\n");
+ exit(1);
+ }
+ }
+ fnbuf[i] = 0;
+
+ // get length of archive member
+ l = 0;
+ c = fgetc(f);
+ l = c << 24;
+ c = fgetc(f);
+ l |= c << 16;
+ c = fgetc(f);
+ l |= c << 8;
+ c = fgetc(f);
+ l |= c;
+
+ for (i = 0; i < nfiles; i++)
+ {
+ if (!strcmp(files[i], fnbuf))
+ break;
+ }
+ if (i < nfiles || nfiles == 0)
+ {
+ // extract the file
+ nf = fopen(fnbuf, "w");
+ if (!nf)
+ {
+ fprintf(stderr, "Cannot extract '%s': %s\n", fnbuf, strerror(errno));
+ exit(1);
+ }
+ while (l)
+ {
+ c = fgetc(f);
+ fputc(c, nf);
+ l--;
+ }
+ fclose(nf);
+ }
+ else
+ {
+ // skip the file
+ fseek(f, l, SEEK_CUR);
+ }
+ }
+}
diff -r 857cb407229e -r bb2665c7005c lwar/lwar.h
--- a/lwar/lwar.h Sun Mar 22 04:24:39 2009 +0000
+++ b/lwar/lwar.h Sun Mar 22 06:51:48 2009 +0000
@@ -25,6 +25,8 @@
#define LWAR_OP_ADD 2
#define LWAR_OP_REMOVE 3
#define LWAR_OP_CREATE 4
+#define LWAR_OP_EXTRACT 5
+#define LWAR_OP_REPLACE 6
#ifndef __lwar_h_seen__
#define __lwar_h_seen__
diff -r 857cb407229e -r bb2665c7005c lwar/main.c
--- a/lwar/main.c Sun Mar 22 04:24:39 2009 +0000
+++ b/lwar/main.c Sun Mar 22 06:51:48 2009 +0000
@@ -63,16 +63,21 @@
mergeflag = 1;
break;
-// case 'r':
-// // remove members
-// operation = LWAR_OP_REMOVE;
-// break;
+ case 'r':
+ // replace members
+ operation = LWAR_OP_REPLACE;
+ break;
case 'l':
// list members
operation = LWAR_OP_LIST;
break;
+ case 'x':
+ // extract members
+ operation = LWAR_OP_EXTRACT;
+ break;
+
case ARGP_KEY_ARG:
if (archive_file)
{
@@ -91,8 +96,10 @@
static struct argp_option options[] =
{
-// { "remove", 'r', 0, 0,
-// "Remove members from the archive" },
+ { "replace", 'r', 0, 0,
+ "Add or replace archive members" },
+ { "extract", 'x', 0, 0,
+ "Extract members from the archive" },
{ "add", 'a', 0, 0,
"Add members to the archive" },
{ "list", 'l', 0, 0,
@@ -117,6 +124,8 @@
extern void do_list(void);
extern void do_add(void);
extern void do_remove(void);
+extern void do_replace(void);
+extern void do_extract(void);
// main function; parse command line, set up assembler state, and run the
// assembler on the first file
@@ -135,7 +144,7 @@
exit(1);
}
- if (operation == LWAR_OP_LIST || operation == LWAR_OP_REMOVE)
+ if (operation == LWAR_OP_LIST || operation == LWAR_OP_REMOVE || operation == LWAR_OP_EXTRACT)
{
struct stat stbuf;
// make sure the archive exists
@@ -186,6 +195,13 @@
do_remove();
break;
+ case LWAR_OP_REPLACE:
+ do_replace();
+ break;
+
+ case LWAR_OP_EXTRACT:
+ do_extract();
+ break;
}
exit(0);
diff -r 857cb407229e -r bb2665c7005c lwar/replace.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lwar/replace.c Sun Mar 22 06:51:48 2009 +0000
@@ -0,0 +1,245 @@
+/*
+replace.c
+Copyright © 2009 William Astle
+
+This file is part of LWAR.
+
+LWAR is free software: you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation, either version 3 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+more details.
+
+You should have received a copy of the GNU General Public License along with
+this program. If not, see .
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include
+#include
+#include
+#include
+
+#include "lwar.h"
+
+void do_replace(void)
+{
+ FILE *f;
+ FILE *nf;
+ unsigned char buf[8];
+ long l;
+ int c;
+ FILE *f2;
+ int i;
+ char fnbuf[1024];
+ char fnbuf2[1024];
+
+ sprintf(fnbuf, "%s.tmp", archive_file);
+
+ f = fopen(archive_file, "r+");
+ if (!f)
+ {
+ if (errno == ENOENT)
+ {
+ nf = fopen(fnbuf, "w");
+ if (nf)
+ {
+ fputs("LWAR1V", nf);
+ goto doadd;
+ }
+ }
+ perror("Cannot open archive file");
+ }
+
+ fread(buf, 1, 6, f);
+ if (memcmp("LWAR1V", buf, 6))
+ {
+ fprintf(stderr, "%s is not a valid archive file.\n", archive_file);
+ exit(1);
+ }
+
+ nf = fopen(fnbuf, "w");
+ if (!nf)
+ {
+ perror("Cannot create temp archive file");
+ exit(1);
+ }
+
+ fputs("LWAR1V", nf);
+
+ for (;;)
+ {
+ c = fgetc(f);
+ if (c == EOF && ferror(f))
+ {
+ perror("Reading archive file");
+ exit(1);
+ }
+ if (c == EOF)
+ goto doadd;
+
+ if (!c)
+ {
+ goto doadd;
+ }
+
+ // find the end of the file name
+ i = 0;
+ while (c)
+ {
+ fnbuf2[i++] = c;
+ c = fgetc(f);
+ if (c == EOF || ferror(f))
+ {
+ fprintf(stderr, "Bad archive file\n");
+ exit(1);
+ }
+ }
+ fnbuf2[i] = 0;
+
+ // get length of archive member
+ l = 0;
+ c = fgetc(f);
+ l = c << 24;
+ c = fgetc(f);
+ l |= c << 16;
+ c = fgetc(f);
+ l |= c << 8;
+ c = fgetc(f);
+ l |= c;
+
+ // is it a file we are replacing? if so, do not copy it
+ for (i = 0; i < nfiles; i++)
+ {
+ if (!strcmp(files[i], fnbuf2))
+ break;
+ }
+ if (i < nfiles)
+ {
+ fseek(f, l, SEEK_CUR);
+ }
+ else
+ {
+ // otherwise, copy it
+ fprintf(nf, "%s", fnbuf2);
+ fputc(0, nf);
+ fputc(l >> 24, nf);
+ fputc((l >> 16) & 0xff, nf);
+ fputc((l >> 8) & 0xff, nf);
+ fputc(l & 0xff, nf);
+ while (l)
+ {
+ c = fgetc(f);
+ fputc(c, nf);
+ l--;
+ }
+ }
+ }
+
+ // done with the original file
+ fclose(f);
+doadd:
+ for (i = 0; i < nfiles; i++)
+ {
+ f2 = fopen(files[i], "r");
+ if (!f2)
+ {
+ fprintf(stderr, "Cannot open file %s:", files[i]);
+ perror("");
+ exit(1);
+ }
+ fread(buf, 1, 6, f2);
+ if (mergeflag && !memcmp("LWAR1V", buf, 6))
+ {
+ // add archive contents...
+ for (;;)
+ {
+ c = fgetc(f2);
+ if (c == EOF || ferror(f2))
+ {
+ perror("Reading input archive file");
+ exit(1);
+ }
+ if (c == EOF)
+ break;
+
+ if (!c)
+ {
+ break;
+ }
+
+ // find the end of the file name
+ while (c)
+ {
+ fputc(c, nf);
+ c = fgetc(f2);
+ if (c == EOF || ferror(f))
+ {
+ fprintf(stderr, "Bad input archive file\n");
+ exit(1);
+ }
+ }
+ fputc(0, nf);
+
+ // get length of archive member
+ l = 0;
+ c = fgetc(f2);
+ fputc(c, nf);
+ l = c << 24;
+ c = fgetc(f2);
+ fputc(c, nf);
+ l |= c << 16;
+ c = fgetc(f2);
+ fputc(c, nf);
+ l |= c << 8;
+ c = fgetc(f2);
+ fputc(c, nf);
+ l |= c;
+
+ while (l)
+ {
+ c = fgetc(f2);
+ fputc(c, nf);
+ l--;
+ }
+ }
+
+ fclose(f2);
+ continue;
+ }
+ fseek(f2, 0, SEEK_END);
+ l = ftell(f2);
+ fseek(f2, 0, SEEK_SET);
+ fputs(files[i], nf);
+ fputc(0, nf);
+ fputc(l >> 24, nf);
+ fputc((l >> 16) & 0xff, nf);
+ fputc((l >> 8) & 0xff, nf);
+ fputc(l & 0xff, nf);
+ while (l)
+ {
+ c = fgetc(f2);
+ fputc(c, nf);
+ l--;
+ }
+ }
+
+ // flag end of file
+ fputc(0, nf);
+
+ fclose(nf);
+
+ if (rename(fnbuf, archive_file) < 0)
+ {
+ perror("Cannot replace old archive file");
+ unlink(fnbuf);
+ }
+}