fix: implemented errmsg

feat: implemented errmsg
This commit is contained in:
Renge 2022-03-04 12:15:43 -05:00
parent 3e1bf8ba92
commit c1c2feb549
5 changed files with 138 additions and 51 deletions

View File

@ -5,15 +5,36 @@
/* Adam M. Costello */ /* Adam M. Costello */
/*********************/ /*********************/
/* This is ANSI C code. */ #include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
/**
* @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 */ * Clear any existing error indication and free storage occupied by
/* write an error message string into errmsg, (indicating */ * any existing error message.
/* failure), being careful not to overrun the space. */ */
void clear_error();
static char * outofmem;
extern const char * const outofmem; /* "Out of memory.\n" */

View File

@ -57,7 +57,7 @@ struct buffer *newbuffer(size_t itemsize)
blk = (struct block *) malloc(sizeof (struct block)); blk = (struct block *) malloc(sizeof (struct block));
items = malloc(maxhere * itemsize); items = malloc(maxhere * itemsize);
if (!buf || !blk || !items) { if (!buf || !blk || !items) {
strcpy(errmsg,outofmem); set_error(outofmem);
goto nberror; goto nberror;
} }
@ -69,7 +69,7 @@ struct buffer *newbuffer(size_t itemsize)
blk->items = items; blk->items = items;
blk->next = NULL; blk->next = NULL;
*errmsg = '\0'; clear_error();
return buf; return buf;
nberror: nberror:
@ -123,7 +123,7 @@ void additem(struct buffer *buf, const void *item)
new = (struct block * ) malloc(sizeof (struct block)); new = (struct block * ) malloc(sizeof (struct block));
items = malloc(maxhere * itemsize); items = malloc(maxhere * itemsize);
if (!new || !items) { if (!new || !items) {
strcpy(errmsg,outofmem); set_error(outofmem);
goto aierror; goto aierror;
} }
blk->next = new; blk->next = new;
@ -140,7 +140,7 @@ void additem(struct buffer *buf, const void *item)
++blk->numhere; ++blk->numhere;
*errmsg = '\0'; clear_error();
return; return;
aierror: aierror:
@ -169,7 +169,7 @@ void *copyitems(struct buffer *buf)
r = malloc(n * itemsize); r = malloc(n * itemsize);
if (!r) { if (!r) {
strcpy(errmsg,outofmem); set_error(outofmem);
return NULL; return NULL;
} }
@ -179,7 +179,7 @@ void *copyitems(struct buffer *buf)
memcpy( ((char *) r) + (blk->numprevious * itemsize), memcpy( ((char *) r) + (blk->numprevious * itemsize),
blk->items, blk->numhere * itemsize); blk->items, blk->numhere * itemsize);
*errmsg = '\0'; clear_error();
return r; return r;
} }

View File

@ -9,8 +9,35 @@
#include "errmsg.h" /* Makes sure we're consistent with the declarations. */ #include "errmsg.h" /* Makes sure we're consistent with the declarations. */
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
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";

View File

@ -80,11 +80,19 @@ static void parseopt(
const char *saveopt = opt; const char *saveopt = opt;
char oc; char oc;
int n, r; int n, r;
FILE *stream;
char *buf;
size_t len;
if (*opt == '-') ++opt; if (*opt == '-') ++opt;
if (!strcmp(opt, "version")) { 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; return;
} }
@ -115,11 +123,16 @@ static void parseopt(
else goto badopt; else goto badopt;
} }
*errmsg = '\0'; clear_error();
return; return;
badopt: 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; char ch, *ln, *nullline = NULL, nullchar = '\0', **lines = NULL;
cbuf = newbuffer(sizeof (char)); cbuf = newbuffer(sizeof (char));
if (*errmsg) goto rlcleanup; if (is_error()) goto rlcleanup;
pbuf = newbuffer(sizeof (char *)); pbuf = newbuffer(sizeof (char *));
if (*errmsg) goto rlcleanup; if (is_error()) goto rlcleanup;
for (blank = 1; ; ) { for (blank = 1; ; ) {
c = getchar(); c = getchar();
@ -148,11 +161,11 @@ static char **readlines(void)
break; break;
} }
additem(cbuf, &nullchar); additem(cbuf, &nullchar);
if (*errmsg) goto rlcleanup; if (is_error()) goto rlcleanup;
ln = copyitems(cbuf); ln = copyitems(cbuf);
if (*errmsg) goto rlcleanup; if (is_error()) goto rlcleanup;
additem(pbuf, &ln); additem(pbuf, &ln);
if (*errmsg) goto rlcleanup; if (is_error()) goto rlcleanup;
clearbuffer(cbuf); clearbuffer(cbuf);
blank = 1; blank = 1;
} }
@ -160,21 +173,21 @@ static char **readlines(void)
if (!isspace(c)) blank = 0; if (!isspace(c)) blank = 0;
ch = c; ch = c;
additem(cbuf, &ch); additem(cbuf, &ch);
if (*errmsg) goto rlcleanup; if (is_error()) goto rlcleanup;
} }
} }
if (!blank) { if (!blank) {
additem(cbuf, &nullchar); additem(cbuf, &nullchar);
if (*errmsg) goto rlcleanup; if (is_error()) goto rlcleanup;
ln = copyitems(cbuf); ln = copyitems(cbuf);
if (*errmsg) goto rlcleanup; if (is_error()) goto rlcleanup;
additem(pbuf, &ln); additem(pbuf, &ln);
if (*errmsg) goto rlcleanup; if (is_error()) goto rlcleanup;
} }
additem(pbuf, &nullline); additem(pbuf, &nullline);
if (*errmsg) goto rlcleanup; if (is_error()) goto rlcleanup;
lines = copyitems(pbuf); lines = copyitems(pbuf);
rlcleanup: rlcleanup:
@ -275,7 +288,7 @@ int original_main(int argc, const char * const *argv)
if (parinit) { if (parinit) {
picopy = malloc((strlen(parinit) + 1) * sizeof (char)); picopy = malloc((strlen(parinit) + 1) * sizeof (char));
if (!picopy) { if (!picopy) {
strcpy(errmsg,outofmem); set_error(outofmem);
goto parcleanup; goto parcleanup;
} }
strcpy(picopy,parinit); strcpy(picopy,parinit);
@ -283,7 +296,7 @@ int original_main(int argc, const char * const *argv)
while (opt) { while (opt) {
parseopt(opt, &widthbak, &prefixbak, parseopt(opt, &widthbak, &prefixbak,
&suffixbak, &hangbak, &lastbak, &minbak); &suffixbak, &hangbak, &lastbak, &minbak);
if (*errmsg) goto parcleanup; if (is_error()) goto parcleanup;
opt = strtok(NULL,whitechars); opt = strtok(NULL,whitechars);
} }
free(picopy); free(picopy);
@ -293,7 +306,7 @@ int original_main(int argc, const char * const *argv)
while (*++argv) { while (*++argv) {
parseopt(*argv, &widthbak, &prefixbak, parseopt(*argv, &widthbak, &prefixbak,
&suffixbak, &hangbak, &lastbak, &minbak); &suffixbak, &hangbak, &lastbak, &minbak);
if (*errmsg) goto parcleanup; if (is_error()) goto parcleanup;
} }
for (;;) { for (;;) {
@ -306,7 +319,7 @@ int original_main(int argc, const char * const *argv)
ungetc(c,stdin); ungetc(c,stdin);
inlines = readlines(); inlines = readlines();
if (*errmsg) goto parcleanup; if (is_error()) goto parcleanup;
if (!*inlines) { if (!*inlines) {
free(inlines); free(inlines);
inlines = NULL; inlines = NULL;
@ -320,7 +333,7 @@ int original_main(int argc, const char * const *argv)
outlines = reformat((const char * const *) inlines, outlines = reformat((const char * const *) inlines,
width, prefix, suffix, hang, last, min); width, prefix, suffix, hang, last, min);
if (*errmsg) goto parcleanup; if (is_error()) goto parcleanup;
freelines(inlines); freelines(inlines);
inlines = NULL; inlines = NULL;
@ -338,8 +351,9 @@ parcleanup:
if (inlines) freelines(inlines); if (inlines) freelines(inlines);
if (outlines) freelines(outlines); if (outlines) freelines(outlines);
if (*errmsg) { if (is_error()) {
fprintf(stderr, "%.163s", errmsg); report_error(stderr);
clear_error();
return(EXIT_FAILURE); return(EXIT_FAILURE);
} }

View File

@ -46,6 +46,9 @@ static int choosebreaks(
int linelen, shortest, newL, score, minlen, diff, sumsqdiff; int linelen, shortest, newL, score, minlen, diff, sumsqdiff;
const char * const impossibility = const char * const impossibility =
"Impossibility #%d has occurred. Please report it.\n"; "Impossibility #%d has occurred. Please report it.\n";
FILE *stream;
char *buf;
size_t len;
/* Determine maximum length of the shortest line: */ /* Determine maximum length of the shortest line: */
@ -72,7 +75,12 @@ static int choosebreaks(
} }
} }
if (w1->score < 0) { 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; return 0;
} }
} }
@ -111,7 +119,12 @@ static int choosebreaks(
newL = head->next ? head->next->score : 0; newL = head->next ? head->next->score : 0;
if (newL > L) { 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; return 0;
} }
} }
@ -145,11 +158,16 @@ static int choosebreaks(
} }
if (head->next && head->next->score < 0) { 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; return 0;
} }
*errmsg = '\0'; clear_error();
return newL; return newL;
} }
@ -162,10 +180,13 @@ char **reformat(const char * const *inlines, int width,
char *q1, *q2, **outlines = NULL; char *q1, *q2, **outlines = NULL;
struct word dummy, *head, *tail, *w1, *w2; struct word dummy, *head, *tail, *w1, *w2;
struct buffer *pbuf = NULL; struct buffer *pbuf = NULL;
FILE *stream;
char *buf;
size_t len;
/* Initialization: */ /* Initialization: */
*errmsg = '\0'; clear_error();
dummy.next = dummy.prev = NULL; dummy.next = dummy.prev = NULL;
head = tail = &dummy; head = tail = &dummy;
@ -179,7 +200,7 @@ char **reformat(const char * const *inlines, int width,
if (numin) { if (numin) {
suffixes = malloc(numin * sizeof (const char *)); suffixes = malloc(numin * sizeof (const char *));
if (!suffixes) { if (!suffixes) {
strcpy(errmsg,outofmem); set_error(outofmem);
goto rfcleanup; goto rfcleanup;
} }
} }
@ -192,9 +213,13 @@ char **reformat(const char * const *inlines, int width,
for (line = inlines, suf = suffixes; *line; ++line, ++suf) { for (line = inlines, suf = suffixes; *line; ++line, ++suf) {
for (end = *line; *end; ++end); for (end = *line; *end; ++end);
if (end - *line < affix) { if (end - *line < affix) {
sprintf(errmsg, stream = open_memstream(&buf, &len);
"Line %ld shorter than <prefix> + <suffix> = %d + %d = %d\n", fprintf(stream,"Line %ld shorter than <prefix> + <suffix> = %d + %d = %d\n",
line - inlines + 1, prefix, suffix, affix); line - inlines + 1, prefix, suffix, affix);
fflush (stream);
set_error(buf);
fclose (stream);
free (buf);
goto rfcleanup; goto rfcleanup;
} }
end -= suffix; end -= suffix;
@ -208,7 +233,7 @@ char **reformat(const char * const *inlines, int width,
if (p2 - p1 > L) p2 = p1 + L; if (p2 - p1 > L) p2 = p1 + L;
w1 = malloc(sizeof (struct word)); w1 = malloc(sizeof (struct word));
if (!w1) { if (!w1) {
strcpy(errmsg,outofmem); set_error(outofmem);
goto rfcleanup; goto rfcleanup;
} }
w1->next = NULL; w1->next = NULL;
@ -235,12 +260,12 @@ char **reformat(const char * const *inlines, int width,
/* Choose line breaks according to policy in "par.doc": */ /* Choose line breaks according to policy in "par.doc": */
newL = choosebreaks(head,tail,L,last,min); newL = choosebreaks(head,tail,L,last,min);
if (*errmsg) goto rfcleanup; if (is_error()) goto rfcleanup;
/* Construct the lines: */ /* Construct the lines: */
pbuf = newbuffer(sizeof (char *)); pbuf = newbuffer(sizeof (char *));
if (*errmsg) goto rfcleanup; if (is_error()) goto rfcleanup;
numout = 0; numout = 0;
w1 = head->next; w1 = head->next;
@ -250,11 +275,11 @@ char **reformat(const char * const *inlines, int width,
prefix; prefix;
q1 = malloc((linelen + 1) * sizeof (char)); q1 = malloc((linelen + 1) * sizeof (char));
if (!q1) { if (!q1) {
strcpy(errmsg,outofmem); set_error(outofmem);
goto rfcleanup; goto rfcleanup;
} }
additem(pbuf, &q1); additem(pbuf, &q1);
if (*errmsg) goto rfcleanup; if (is_error()) goto rfcleanup;
++numout; ++numout;
q2 = q1 + prefix; q2 = q1 + prefix;
if (numout <= numin) memcpy(q1, inlines[numout - 1], prefix); if (numout <= numin) memcpy(q1, inlines[numout - 1], prefix);
@ -281,7 +306,7 @@ char **reformat(const char * const *inlines, int width,
q1 = NULL; q1 = NULL;
additem(pbuf, &q1); additem(pbuf, &q1);
if (*errmsg) goto rfcleanup; if (is_error()) goto rfcleanup;
outlines = copyitems(pbuf); outlines = copyitems(pbuf);