From c1c2feb549fb917d51d8e4973b4d393e11e38280 Mon Sep 17 00:00:00 2001 From: Renge Date: Fri, 4 Mar 2022 12:15:43 -0500 Subject: [PATCH] fix: implemented errmsg feat: implemented errmsg --- hw2/include/errmsg.h | 39 ++++++++++++++++++++++++-------- hw2/src/buffer.c | 12 +++++----- hw2/src/errmsg.c | 31 +++++++++++++++++++++++-- hw2/src/par.c | 54 ++++++++++++++++++++++++++++---------------- hw2/src/reformat.c | 53 +++++++++++++++++++++++++++++++------------ 5 files changed, 138 insertions(+), 51 deletions(-) diff --git a/hw2/include/errmsg.h b/hw2/include/errmsg.h index d68dce1..2798518 100644 --- a/hw2/include/errmsg.h +++ b/hw2/include/errmsg.h @@ -5,15 +5,36 @@ /* Adam M. Costello */ /*********************/ -/* This is ANSI C code. */ +#include +#include +#include +#include +/** + * @brief Set an error indication, with a specified error message. + * @param msg Pointer to the error message. The string passed by the caller + * will be copied. + */ +void set_error(char *msg); +/** + * @brief Test whether there is currently an error indication. + * @return 1 if an error indication currently exists, 0 otherwise. + */ +int is_error(); -extern char errmsg[163]; +/** + * @brief Issue any existing error message to the specified output stream. + * @param file Stream to which the error message is to be issued. + * @return 0 if either there was no existing error message, or else there + * was an existing error message and it was successfully output. + * Return non-zero if the attempt to output an existing error message + * failed. + */ +int report_error(FILE *file); -/* Any function which uses errmsg must, before returning, */ -/* either set errmsg[0] to '\0' (indicating success), or */ -/* write an error message string into errmsg, (indicating */ -/* failure), being careful not to overrun the space. */ - - -extern const char * const outofmem; /* "Out of memory.\n" */ +/** + * Clear any existing error indication and free storage occupied by + * any existing error message. + */ +void clear_error(); +static char * outofmem; \ No newline at end of file diff --git a/hw2/src/buffer.c b/hw2/src/buffer.c index d23f57b..aa3b114 100644 --- a/hw2/src/buffer.c +++ b/hw2/src/buffer.c @@ -57,7 +57,7 @@ struct buffer *newbuffer(size_t itemsize) blk = (struct block *) malloc(sizeof (struct block)); items = malloc(maxhere * itemsize); if (!buf || !blk || !items) { - strcpy(errmsg,outofmem); + set_error(outofmem); goto nberror; } @@ -69,7 +69,7 @@ struct buffer *newbuffer(size_t itemsize) blk->items = items; blk->next = NULL; - *errmsg = '\0'; + clear_error(); return buf; nberror: @@ -123,7 +123,7 @@ void additem(struct buffer *buf, const void *item) new = (struct block * ) malloc(sizeof (struct block)); items = malloc(maxhere * itemsize); if (!new || !items) { - strcpy(errmsg,outofmem); + set_error(outofmem); goto aierror; } blk->next = new; @@ -140,7 +140,7 @@ void additem(struct buffer *buf, const void *item) ++blk->numhere; - *errmsg = '\0'; + clear_error(); return; aierror: @@ -169,7 +169,7 @@ void *copyitems(struct buffer *buf) r = malloc(n * itemsize); if (!r) { - strcpy(errmsg,outofmem); + set_error(outofmem); return NULL; } @@ -179,7 +179,7 @@ void *copyitems(struct buffer *buf) memcpy( ((char *) r) + (blk->numprevious * itemsize), blk->items, blk->numhere * itemsize); - *errmsg = '\0'; + clear_error(); return r; } diff --git a/hw2/src/errmsg.c b/hw2/src/errmsg.c index 3d9b9e9..74bbb04 100644 --- a/hw2/src/errmsg.c +++ b/hw2/src/errmsg.c @@ -9,8 +9,35 @@ #include "errmsg.h" /* Makes sure we're consistent with the declarations. */ +#include +#include +#include +#include +static char *errmsg = NULL; -char errmsg[163]; +void set_error(char *msg) +{ + errmsg = strdup(msg); +} -const char * const outofmem = "Out of memory.\n"; +int is_error() { + return errmsg ? 1 : 0; +} + +int report_error(FILE *file) { + if (is_error()) + { + return fputs(errmsg, file) < 0 ? 1 : 0; + } + return 0; +} + +void clear_error() { + if (is_error()) + { + free(errmsg); + errmsg = NULL; + } +} +static char *outofmem = "Out of memory.\n"; diff --git a/hw2/src/par.c b/hw2/src/par.c index fa679af..7a33854 100644 --- a/hw2/src/par.c +++ b/hw2/src/par.c @@ -80,11 +80,19 @@ static void parseopt( const char *saveopt = opt; char oc; int n, r; + FILE *stream; + char *buf; + size_t len; if (*opt == '-') ++opt; if (!strcmp(opt, "version")) { - sprintf(errmsg, "%s %s\n", progname, version); + stream = open_memstream(&buf, &len); + fprintf(stream, "%s %s\n", progname, version); + fflush (stream); + set_error(buf); + fclose (stream); + free (buf); return; } @@ -115,11 +123,16 @@ static void parseopt( else goto badopt; } - *errmsg = '\0'; + clear_error(); return; badopt: - sprintf(errmsg, "Bad option: %.149s\n", saveopt); + stream = open_memstream(&buf, &len); + fprintf(stream,"Bad option: %.149s\n", saveopt); + fflush (stream); + set_error(buf); + fclose (stream); + free (buf); } @@ -135,9 +148,9 @@ static char **readlines(void) char ch, *ln, *nullline = NULL, nullchar = '\0', **lines = NULL; cbuf = newbuffer(sizeof (char)); - if (*errmsg) goto rlcleanup; + if (is_error()) goto rlcleanup; pbuf = newbuffer(sizeof (char *)); - if (*errmsg) goto rlcleanup; + if (is_error()) goto rlcleanup; for (blank = 1; ; ) { c = getchar(); @@ -148,11 +161,11 @@ static char **readlines(void) break; } additem(cbuf, &nullchar); - if (*errmsg) goto rlcleanup; + if (is_error()) goto rlcleanup; ln = copyitems(cbuf); - if (*errmsg) goto rlcleanup; + if (is_error()) goto rlcleanup; additem(pbuf, &ln); - if (*errmsg) goto rlcleanup; + if (is_error()) goto rlcleanup; clearbuffer(cbuf); blank = 1; } @@ -160,21 +173,21 @@ static char **readlines(void) if (!isspace(c)) blank = 0; ch = c; additem(cbuf, &ch); - if (*errmsg) goto rlcleanup; + if (is_error()) goto rlcleanup; } } if (!blank) { additem(cbuf, &nullchar); - if (*errmsg) goto rlcleanup; + if (is_error()) goto rlcleanup; ln = copyitems(cbuf); - if (*errmsg) goto rlcleanup; + if (is_error()) goto rlcleanup; additem(pbuf, &ln); - if (*errmsg) goto rlcleanup; + if (is_error()) goto rlcleanup; } additem(pbuf, &nullline); - if (*errmsg) goto rlcleanup; + if (is_error()) goto rlcleanup; lines = copyitems(pbuf); rlcleanup: @@ -275,7 +288,7 @@ int original_main(int argc, const char * const *argv) if (parinit) { picopy = malloc((strlen(parinit) + 1) * sizeof (char)); if (!picopy) { - strcpy(errmsg,outofmem); + set_error(outofmem); goto parcleanup; } strcpy(picopy,parinit); @@ -283,7 +296,7 @@ int original_main(int argc, const char * const *argv) while (opt) { parseopt(opt, &widthbak, &prefixbak, &suffixbak, &hangbak, &lastbak, &minbak); - if (*errmsg) goto parcleanup; + if (is_error()) goto parcleanup; opt = strtok(NULL,whitechars); } free(picopy); @@ -293,7 +306,7 @@ int original_main(int argc, const char * const *argv) while (*++argv) { parseopt(*argv, &widthbak, &prefixbak, &suffixbak, &hangbak, &lastbak, &minbak); - if (*errmsg) goto parcleanup; + if (is_error()) goto parcleanup; } for (;;) { @@ -306,7 +319,7 @@ int original_main(int argc, const char * const *argv) ungetc(c,stdin); inlines = readlines(); - if (*errmsg) goto parcleanup; + if (is_error()) goto parcleanup; if (!*inlines) { free(inlines); inlines = NULL; @@ -320,7 +333,7 @@ int original_main(int argc, const char * const *argv) outlines = reformat((const char * const *) inlines, width, prefix, suffix, hang, last, min); - if (*errmsg) goto parcleanup; + if (is_error()) goto parcleanup; freelines(inlines); inlines = NULL; @@ -338,8 +351,9 @@ parcleanup: if (inlines) freelines(inlines); if (outlines) freelines(outlines); - if (*errmsg) { - fprintf(stderr, "%.163s", errmsg); + if (is_error()) { + report_error(stderr); + clear_error(); return(EXIT_FAILURE); } diff --git a/hw2/src/reformat.c b/hw2/src/reformat.c index 0c1d1b0..88888d2 100644 --- a/hw2/src/reformat.c +++ b/hw2/src/reformat.c @@ -46,6 +46,9 @@ static int choosebreaks( int linelen, shortest, newL, score, minlen, diff, sumsqdiff; const char * const impossibility = "Impossibility #%d has occurred. Please report it.\n"; + FILE *stream; + char *buf; + size_t len; /* Determine maximum length of the shortest line: */ @@ -72,7 +75,12 @@ static int choosebreaks( } } if (w1->score < 0) { - sprintf(errmsg,impossibility,1); + stream = open_memstream(&buf, &len); + fprintf(stream,impossibility,1); + fflush (stream); + set_error(buf); + fclose (stream); + free (buf); return 0; } } @@ -111,7 +119,12 @@ static int choosebreaks( newL = head->next ? head->next->score : 0; if (newL > L) { - sprintf(errmsg,impossibility,2); + stream = open_memstream(&buf, &len); + fprintf(stream,impossibility,2); + fflush (stream); + set_error(buf); + fclose (stream); + free (buf); return 0; } } @@ -145,11 +158,16 @@ static int choosebreaks( } if (head->next && head->next->score < 0) { - sprintf(errmsg,impossibility,3); + stream = open_memstream(&buf, &len); + fprintf(stream,impossibility,3); + fflush (stream); + set_error(buf); + fclose (stream); + free (buf); return 0; } - *errmsg = '\0'; + clear_error(); return newL; } @@ -162,10 +180,13 @@ char **reformat(const char * const *inlines, int width, char *q1, *q2, **outlines = NULL; struct word dummy, *head, *tail, *w1, *w2; struct buffer *pbuf = NULL; + FILE *stream; + char *buf; + size_t len; /* Initialization: */ - *errmsg = '\0'; + clear_error(); dummy.next = dummy.prev = NULL; head = tail = &dummy; @@ -179,7 +200,7 @@ char **reformat(const char * const *inlines, int width, if (numin) { suffixes = malloc(numin * sizeof (const char *)); if (!suffixes) { - strcpy(errmsg,outofmem); + set_error(outofmem); goto rfcleanup; } } @@ -192,9 +213,13 @@ char **reformat(const char * const *inlines, int width, for (line = inlines, suf = suffixes; *line; ++line, ++suf) { for (end = *line; *end; ++end); if (end - *line < affix) { - sprintf(errmsg, - "Line %ld shorter than + = %d + %d = %d\n", + stream = open_memstream(&buf, &len); + fprintf(stream,"Line %ld shorter than + = %d + %d = %d\n", line - inlines + 1, prefix, suffix, affix); + fflush (stream); + set_error(buf); + fclose (stream); + free (buf); goto rfcleanup; } end -= suffix; @@ -208,7 +233,7 @@ char **reformat(const char * const *inlines, int width, if (p2 - p1 > L) p2 = p1 + L; w1 = malloc(sizeof (struct word)); if (!w1) { - strcpy(errmsg,outofmem); + set_error(outofmem); goto rfcleanup; } w1->next = NULL; @@ -235,12 +260,12 @@ char **reformat(const char * const *inlines, int width, /* Choose line breaks according to policy in "par.doc": */ newL = choosebreaks(head,tail,L,last,min); - if (*errmsg) goto rfcleanup; + if (is_error()) goto rfcleanup; /* Construct the lines: */ pbuf = newbuffer(sizeof (char *)); - if (*errmsg) goto rfcleanup; + if (is_error()) goto rfcleanup; numout = 0; w1 = head->next; @@ -250,11 +275,11 @@ char **reformat(const char * const *inlines, int width, prefix; q1 = malloc((linelen + 1) * sizeof (char)); if (!q1) { - strcpy(errmsg,outofmem); + set_error(outofmem); goto rfcleanup; } additem(pbuf, &q1); - if (*errmsg) goto rfcleanup; + if (is_error()) goto rfcleanup; ++numout; q2 = q1 + prefix; if (numout <= numin) memcpy(q1, inlines[numout - 1], prefix); @@ -281,7 +306,7 @@ char **reformat(const char * const *inlines, int width, q1 = NULL; additem(pbuf, &q1); - if (*errmsg) goto rfcleanup; + if (is_error()) goto rfcleanup; outlines = copyitems(pbuf);