fix: implemented errmsg
feat: implemented errmsg
This commit is contained in:
parent
3e1bf8ba92
commit
c1c2feb549
|
@ -5,15 +5,36 @@
|
|||
/* 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 */
|
||||
/* 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;
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,8 +9,35 @@
|
|||
|
||||
|
||||
#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";
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <prefix> + <suffix> = %d + %d = %d\n",
|
||||
stream = open_memstream(&buf, &len);
|
||||
fprintf(stream,"Line %ld shorter than <prefix> + <suffix> = %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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user