scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

commit 077526434528bec1791fc554bcbec556a6c21088
parent 355c64cd5eeb10a365b65b89e51384c61f55cadf
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Fri, 24 Nov 2017 14:58:15 +0000

[ar] Add functions to write ar files

At this moment this functions are placed in the
library but maybe the own ar source code is a
better place since they are not expected to be
used in any other place.

Diffstat:
ar/main.c | 58++++++++++++++++++++++++----------------------------------
inc/ar.h | 17+++++++++++++++++
lib/scc/libdep.mk | 1+
lib/scc/war.c | 38++++++++++++++++++++++++++++++++++++++
4 files changed, 80 insertions(+), 34 deletions(-)

diff --git a/ar/main.c b/ar/main.c @@ -7,6 +7,9 @@ static char sccsid[] = "@(#) ./ar/main.c"; #include <stat.h> +#include "../inc/scc.h" +#include "../inc/ar.h" + int main(int argc, char *argv[]) { @@ -15,47 +18,31 @@ main(int argc, char *argv[]) FILE *fp, *arfile; char *fname, *arname = "lib.a"; struct stat st; + struct arhdr hdr; if ((arfile = fopen(arname, "wb")) == NULL) { perror("ar:error opening library file"); exit(1); } - fputs("!<arch>\n", arfile); + fputs(ARMAGIC, arfile); while ((fname = *++argv) != NULL) { - if ((n = strlen(fname)) > 16) { - fprintf(stderr, "ar:too long file name '%s'\n", fname); - exit(3); - } - if (stat(fname, &st) < 0) { - fprintf(stderr, - "ar:error opening object file '%s':%s\n", - fname, strerror(errno)); - exit(2); - } - fprintf(arfile, - "%-16s%-12llu%-6u%-6u%-8o%-10llu`\n", - fname, - (unsigned long long) st.st_atime, - (int) st.st_uid, (int) st.st_gid, - (int) st.st_mode, - (unsigned long long) st.st_size); - if ((fp = fopen(fname, "rb")) == NULL) { - fprintf(stderr, - "ar: error opening file '%s':%s\n", - fname, strerror(errno)); - exit(3); - } - while ((c = getc(fp)) != EOF) - putc(c, arfile); - if (st.st_size & 1) - putc('\n', arfile); - if (fclose(fp)) { - fprintf(stderr, - "ar:error reading from input file '%s':%s\n", - fname, strerror(errno)); - exit(4); - } + if ((n = strlen(fname)) > ARNAME_SIZ) + die("ar: %s: too long file name", fname); + if (stat(fname, &st) < 0) + goto member_error; + + strcpy(hdr.name, fname); + hdr.time = st.st_atime; + hdr.uid = st.st_uid; + hdr.gid = st.st_gid; + hdr.mode = st.st_mode; + hdr.size = st.st_mode; + + if (wrarhdr(arfile, &hdr) < 0) + goto member_error; + if (wrarfile(arfile, &hdr) < 0) + goto member_error; } if (fclose(arfile)) { @@ -65,4 +52,7 @@ main(int argc, char *argv[]) } return 0; + +member_error: + die("ar: %s: %s", fname, strerror(errno)); } diff --git a/inc/ar.h b/inc/ar.h @@ -1,3 +1,20 @@ #define ARMAGIC "!<arch>\n" #define ARMAGIC_SIZ 8 + +struct arhdr { + char name[17]; + unsigned long long time; + int uid; + int gid; + int mode; + unsigned long long size; +}; + +#define ARHDR_SIZ 60 +#define ARNAME_SIZ 16 +#define ARMAGIC "!<arch>\n" +#define ARMAGIC_SIZ 8 + +extern int wrarhdr(FILE *fp, struct arhdr *hdr); +extern int wrarfile(FILE *fp, struct arhdr *hdr); diff --git a/lib/scc/libdep.mk b/lib/scc/libdep.mk @@ -11,3 +11,4 @@ LIB-OBJ = $(LIBDIR)/debug.o \ $(LIBDIR)/lpack.o \ $(LIBDIR)/wmyro.o \ $(LIBDIR)/rmyro.o \ + $(LIBDIR)/war.o \ diff --git a/lib/scc/war.c b/lib/scc/war.c @@ -0,0 +1,38 @@ +static char sccsid[] = "@(#) ./lib/scc/war.c"; + +#include <assert.h> +#include <stdio.h> + +#include "../../inc/ar.h" + +int +wrarhdr(FILE *fp, struct arhdr *hdr) +{ + int len; + + len = fprintf(fp, + "%-16s%-12llu%-6u%-6u%-8o%-10llu`\n", + hdr->name, + hdr->time, + hdr->uid, hdr->gid, + hdr->mode, + hdr->size); + assert(len== ARHDR_SIZ); + + return (feof(fp)) ? EOF : len; +} + +int +wrarfile(FILE *fo, struct arhdr *hdr) +{ + FILE *fi; + int c; + + if ((fi = fopen(hdr->name, "rb")) == NULL) + return -1; + while ((c = getc(fi)) != EOF) + putc(c, fo); + if (hdr->size & 1) + putc('\n', fo); + return (fclose(fi) == EOF) ? -1 : 0; +}