i think i fixed it
This commit is contained in:
parent
cc943d045e
commit
0398d9ca94
248
mm/mm.c
248
mm/mm.c
@ -20,7 +20,7 @@
|
|||||||
#include <signal.h> /* signal(2), SIG_ERR, SIG_IGN, SIGINT */
|
#include <signal.h> /* signal(2), SIG_ERR, SIG_IGN, SIGINT */
|
||||||
#include <stdio.h> /* fclose(3), fopen(3), fprintf(3), getc(3), putc(3),
|
#include <stdio.h> /* fclose(3), fopen(3), fprintf(3), getc(3), putc(3),
|
||||||
* setvbuf(3), size_t, _IONBF, NULL */
|
* setvbuf(3), size_t, _IONBF, NULL */
|
||||||
#include <stdlib.h> /* free(3), realloc(3) */
|
#include <stdlib.h> /* free(3), malloc(3), realloc(3) */
|
||||||
#include <string.h> /* strerror(3) */
|
#include <string.h> /* strerror(3) */
|
||||||
#include <unistd.h> /* getopt(3) */
|
#include <unistd.h> /* getopt(3) */
|
||||||
#if !defined EX_OSERR || !defined EX_USAGE
|
#if !defined EX_OSERR || !defined EX_USAGE
|
||||||
@ -55,152 +55,35 @@ static char *stderr_name = "<stderr>";
|
|||||||
static char *(fmode[]) = { (char []){"rb"}, (char []){"rb+"} };
|
static char *(fmode[]) = { (char []){"rb"}, (char []){"rb+"} };
|
||||||
static char *wharsh = "wb";
|
static char *wharsh = "wb";
|
||||||
|
|
||||||
/* Grows the files allocations by ALLOC_INCREMENT. */
|
|
||||||
#define Files_grow(files) (\
|
|
||||||
(files->files = realloc(files->files, \
|
|
||||||
(files->a += ALLOC_INCREMENT) \
|
|
||||||
* sizeof *(files->files))) == NULL \
|
|
||||||
|| (files->names = realloc(files->names, \
|
|
||||||
files->a * sizeof *(files->names))) == NULL \
|
|
||||||
? NULL \
|
|
||||||
: files \
|
|
||||||
)
|
|
||||||
|
|
||||||
/* Opens the file at the path p and puts it in the files struct, returning NULL
|
/* Opens the file at the path p and puts it in the files struct, returning NULL
|
||||||
* if either the opening or the placement of the open FILE pointer fail. */
|
* if either the opening or the placement of the open FILE pointer fail. */
|
||||||
#define Files_fopen(files, p) \
|
#define Files_open(files, p) \
|
||||||
Files_fappend((files), fopen((p), (files)->mode), (p))
|
Files_append((files), fopen((p), (files)->mode), (p))
|
||||||
|
|
||||||
/* Destructs the files[2] used by main. */
|
|
||||||
#define terminate(files) do{ \
|
|
||||||
Files_destruct(&(files)[0]); \
|
|
||||||
Files_destruct(&(files)[1]); }while(0)
|
|
||||||
|
|
||||||
static struct Files *Files_initialize(struct Files *files);
|
|
||||||
/* Destructs a files struct by closing its files and freeing its files and
|
|
||||||
* names arrays. Returns the destructed files. */
|
|
||||||
static struct Files *
|
|
||||||
Files_destruct(struct Files *files){
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for(i = 0; i < files->s; fclose(files->files[i++]));
|
|
||||||
free(files->files);
|
|
||||||
free(files->names);
|
|
||||||
|
|
||||||
return Files_initialize(files);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Adds the open FILE pointer for the file at the path s to the files struct,
|
/* Adds the open FILE pointer for the file at the path s to the files struct,
|
||||||
* returning the FILE if successful and NULL if not. */
|
* returning the FILE if successful and NULL if not, allocating more memory in
|
||||||
|
* the files buffers as needed. */
|
||||||
static FILE *
|
static FILE *
|
||||||
Files_fappend(struct Files *files, FILE *file, char *name){
|
Files_append(struct Files *files, FILE *file, char *name){
|
||||||
|
|
||||||
if(files->s == -1)
|
if(files->s == -1)
|
||||||
files->s = 0;
|
files->s = 0;
|
||||||
|
|
||||||
if(file == NULL || Files_grow(files) == NULL)
|
if(file == NULL || (files->s == files->a
|
||||||
|
&& ((files->files = realloc(files->files,
|
||||||
|
(files->a += (files->a == 0)
|
||||||
|
? ALLOC_INITIAL
|
||||||
|
: ALLOC_INCREMENT)
|
||||||
|
* sizeof *(files->files))) == NULL
|
||||||
|
|| (files->names = realloc(files->names,
|
||||||
|
files->a * sizeof *(files->names)))
|
||||||
|
== NULL)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
files->names[files->s] = name;
|
files->names[files->s] = name;
|
||||||
return files->files[files->s++] = file;
|
return files->files[files->s++] = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns the first index within files->files of the given FILE pointer f. If
|
|
||||||
* f isn't within files->files, returns -1. */
|
|
||||||
static int
|
|
||||||
Files_fileindex(struct Files *files, FILE *f){
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
for(i = 0; i < files->s; ++i)
|
|
||||||
if(files->files[i] == f)
|
|
||||||
return i;
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Returns the corresponding file name in the files struct to the FILE pointer
|
|
||||||
* f, or NULL if f is NULL or isn't in files->files. */
|
|
||||||
static char *
|
|
||||||
Files_filename(struct Files *files, FILE *f){
|
|
||||||
int i;
|
|
||||||
|
|
||||||
return (f == NULL || (i = Files_fileindex(files, f)) == -1)
|
|
||||||
? NULL
|
|
||||||
: files->names[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct Files *Files_fremove(struct Files *files, FILE *f);
|
|
||||||
static FILE *Files_nextfile(struct Files *files, FILE *f);
|
|
||||||
/* Prints c to all files, returning c. If a stream can't be written, a
|
|
||||||
* message is printed to standard error and the stream is closed and removed
|
|
||||||
* from files. If no stream can be written, returns EOF. */
|
|
||||||
static int
|
|
||||||
Io_fputc(struct Files *files, int c){
|
|
||||||
FILE *f;
|
|
||||||
FILE *lf;
|
|
||||||
char *ln;
|
|
||||||
|
|
||||||
f = NULL;
|
|
||||||
lf = NULL;
|
|
||||||
for(f = NULL; (f = Files_nextfile(files, f)) != NULL;){
|
|
||||||
if(lf != NULL){
|
|
||||||
if(fclose(lf) == EOF)
|
|
||||||
fprintf(stderr, "%s: %s: %s\n",
|
|
||||||
program_name, ln, strerror(errno));
|
|
||||||
if(Files_fremove(files, lf)->s == 0)
|
|
||||||
return EOF;
|
|
||||||
lf = NULL;
|
|
||||||
}
|
|
||||||
if(putc(c, f) == EOF)
|
|
||||||
ln = Files_filename(files, lf = f);
|
|
||||||
}
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Removes a given file pointer f from the given files struct, returning NULL
|
|
||||||
* if the file was already absent from files and otherwise files. */
|
|
||||||
static struct Files *
|
|
||||||
Files_fremove(struct Files *files, FILE *f){
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
if((i = Files_fileindex(files, f)) == -1)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for(; i < files->s - 1; ++i){
|
|
||||||
files->files[i] = files->files[i + 1];
|
|
||||||
files->names[i] = files->names[i + 1];
|
|
||||||
}
|
|
||||||
--files->s;
|
|
||||||
|
|
||||||
return files;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initializes the members of the given files struct and returns files. */
|
|
||||||
static struct Files *
|
|
||||||
Files_initialize(struct Files *files){
|
|
||||||
|
|
||||||
files->a = 0;
|
|
||||||
files->s = 0;
|
|
||||||
files->files = NULL;
|
|
||||||
files->names = NULL;
|
|
||||||
|
|
||||||
return files;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Returns the first file in files if f is NULL, NULL if the file is the last
|
|
||||||
* in or absent from files, or the file after f in files. */
|
|
||||||
static FILE *
|
|
||||||
Files_nextfile(struct Files *files, FILE *f){
|
|
||||||
int i;
|
|
||||||
|
|
||||||
return (f == NULL)
|
|
||||||
? files->files[0]
|
|
||||||
: ((i = Files_fileindex(files, f)) == -1 || i == files->s - 1)
|
|
||||||
? NULL
|
|
||||||
: files->files[i + 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Prints a diagnostic message based on errno and returns an exit status
|
/* Prints a diagnostic message based on errno and returns an exit status
|
||||||
* appropriate for an OS error. */
|
* appropriate for an OS error. */
|
||||||
static int
|
static int
|
||||||