feat: implemented getopt_long
This commit is contained in:
parent
c1c2feb549
commit
7d21448432
519
hw2/src/par.c
519
hw2/src/par.c
|
@ -7,47 +7,43 @@
|
||||||
|
|
||||||
/* This is ANSI C code. */
|
/* This is ANSI C code. */
|
||||||
|
|
||||||
|
|
||||||
#include "errmsg.h"
|
#include "errmsg.h"
|
||||||
#include "buffer.h" /* Also includes <stddef.h>. */
|
#include "buffer.h" /* Also includes <stddef.h>. */
|
||||||
#include "reformat.h"
|
#include "reformat.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
#undef NULL
|
#undef NULL
|
||||||
#define NULL ((void *) 0)
|
#define NULL ((void *)0)
|
||||||
|
|
||||||
|
|
||||||
const char * const progname = "par";
|
|
||||||
const char * const version = "3.20";
|
|
||||||
|
|
||||||
|
const char *const progname = "par";
|
||||||
|
const char *const version = "3.20";
|
||||||
|
|
||||||
static int digtoint(char c)
|
static int digtoint(char c)
|
||||||
|
|
||||||
/* Returns the value represented by the digit c, */
|
/* Returns the value represented by the digit c, */
|
||||||
/* or -1 if c is not a digit. Does not use errmsg. */
|
/* or -1 if c is not a digit. Does not use errmsg. */
|
||||||
{
|
{
|
||||||
return c == '0' ? 0 :
|
return c == '0' ? 0 : c == '1' ? 1
|
||||||
c == '1' ? 1 :
|
: c == '2' ? 2
|
||||||
c == '2' ? 2 :
|
: c == '3' ? 3
|
||||||
c == '3' ? 3 :
|
: c == '4' ? 4
|
||||||
c == '4' ? 4 :
|
: c == '5' ? 5
|
||||||
c == '5' ? 5 :
|
: c == '6' ? 6
|
||||||
c == '6' ? 6 :
|
: c == '7' ? 7
|
||||||
c == '7' ? 7 :
|
: c == '8' ? 8
|
||||||
c == '8' ? 8 :
|
: c == '9' ? 9
|
||||||
c == '9' ? 9 :
|
: -1;
|
||||||
-1;
|
|
||||||
|
|
||||||
/* We can't simply return c - '0' because this is ANSI */
|
/* We can't simply return c - '0' because this is ANSI */
|
||||||
/* C code, so it has to work for any character set, not */
|
/* C code, so it has to work for any character set, not */
|
||||||
/* just ones which put the digits together in order. */
|
/* just ones which put the digits together in order. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int strtoudec(const char *s, int *pn)
|
static int strtoudec(const char *s, int *pn)
|
||||||
|
|
||||||
/* Puts the decimal value of the string s into *pn, returning */
|
/* Puts the decimal value of the string s into *pn, returning */
|
||||||
|
@ -57,10 +53,13 @@ static int strtoudec(const char *s, int *pn)
|
||||||
{
|
{
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
if (!*s) return 0;
|
if (!*s)
|
||||||
|
return 0;
|
||||||
|
|
||||||
do {
|
do
|
||||||
if (n >= 1000 || !isdigit(*s)) return 0;
|
{
|
||||||
|
if (n >= 1000 || !isdigit(*s))
|
||||||
|
return 0;
|
||||||
n = 10 * n + digtoint(*s);
|
n = 10 * n + digtoint(*s);
|
||||||
} while (*++s);
|
} while (*++s);
|
||||||
|
|
||||||
|
@ -69,11 +68,9 @@ static int strtoudec(const char *s, int *pn)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void parseopt(
|
static void parseopt(
|
||||||
const char *opt, int *pwidth, int *pprefix,
|
const char *opt, int *pwidth, int *pprefix,
|
||||||
int *psuffix, int *phang, int *plast, int *pmin
|
int *psuffix, int *phang, int *plast, int *pmin)
|
||||||
)
|
|
||||||
/* Parses the single option in opt, setting *pwidth, *pprefix, */
|
/* Parses the single option in opt, setting *pwidth, *pprefix, */
|
||||||
/* *psuffix, *phang, *plast, or *pmin as appropriate. Uses errmsg. */
|
/* *psuffix, *phang, *plast, or *pmin as appropriate. Uses errmsg. */
|
||||||
{
|
{
|
||||||
|
@ -84,43 +81,62 @@ static void parseopt(
|
||||||
char *buf;
|
char *buf;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
if (*opt == '-') ++opt;
|
if (*opt == '-')
|
||||||
|
++opt;
|
||||||
|
|
||||||
if (!strcmp(opt, "version")) {
|
if (!strcmp(opt, "version"))
|
||||||
|
{
|
||||||
stream = open_memstream(&buf, &len);
|
stream = open_memstream(&buf, &len);
|
||||||
fprintf(stream, "%s %s\n", progname, version);
|
fprintf(stream, "%s %s\n", progname, version);
|
||||||
fflush (stream);
|
fflush(stream);
|
||||||
set_error(buf);
|
set_error(buf);
|
||||||
fclose (stream);
|
fclose(stream);
|
||||||
free (buf);
|
free(buf);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
oc = *opt;
|
oc = *opt;
|
||||||
|
|
||||||
if (isdigit(oc)) {
|
if (isdigit(oc))
|
||||||
if (!strtoudec(opt, &n)) goto badopt;
|
{
|
||||||
if (n <= 8) *pprefix = n;
|
if (!strtoudec(opt, &n))
|
||||||
else *pwidth = n;
|
goto badopt;
|
||||||
|
if (n <= 8)
|
||||||
|
*pprefix = n;
|
||||||
|
else
|
||||||
|
*pwidth = n;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
if (!oc) goto badopt;
|
{
|
||||||
|
if (!oc)
|
||||||
|
goto badopt;
|
||||||
n = 1;
|
n = 1;
|
||||||
r = strtoudec(opt + 1, &n);
|
r = strtoudec(opt + 1, &n);
|
||||||
if (opt[1] && !r) goto badopt;
|
if (opt[1] && !r)
|
||||||
|
goto badopt;
|
||||||
|
|
||||||
if (oc == 'w' || oc == 'p' || oc == 's') {
|
if (oc == 'w' || oc == 'p' || oc == 's')
|
||||||
if (!r) goto badopt;
|
{
|
||||||
if (oc == 'w') *pwidth = n;
|
if (!r)
|
||||||
else if (oc == 'p') *pprefix = n;
|
goto badopt;
|
||||||
else *psuffix = n;
|
if (oc == 'w')
|
||||||
|
*pwidth = n;
|
||||||
|
else if (oc == 'p')
|
||||||
|
*pprefix = n;
|
||||||
|
else
|
||||||
|
*psuffix = n;
|
||||||
}
|
}
|
||||||
else if (oc == 'h') *phang = n;
|
else if (oc == 'h')
|
||||||
else if (n <= 1) {
|
*phang = n;
|
||||||
if (oc == 'l') *plast = n;
|
else if (n <= 1)
|
||||||
else if (oc == 'm') *pmin = n;
|
{
|
||||||
|
if (oc == 'l')
|
||||||
|
*plast = n;
|
||||||
|
else if (oc == 'm')
|
||||||
|
*pmin = n;
|
||||||
}
|
}
|
||||||
else goto badopt;
|
else
|
||||||
|
goto badopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
clear_error();
|
clear_error();
|
||||||
|
@ -128,14 +144,13 @@ static void parseopt(
|
||||||
|
|
||||||
badopt:
|
badopt:
|
||||||
stream = open_memstream(&buf, &len);
|
stream = open_memstream(&buf, &len);
|
||||||
fprintf(stream,"Bad option: %.149s\n", saveopt);
|
fprintf(stream, "Bad option: %.149s\n", saveopt);
|
||||||
fflush (stream);
|
fflush(stream);
|
||||||
set_error(buf);
|
set_error(buf);
|
||||||
fclose (stream);
|
fclose(stream);
|
||||||
free (buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static char **readlines(void)
|
static char **readlines(void)
|
||||||
|
|
||||||
/* Reads lines from stdin until EOF, or until a blank line is encountered, */
|
/* Reads lines from stdin until EOF, or until a blank line is encountered, */
|
||||||
|
@ -147,57 +162,79 @@ static char **readlines(void)
|
||||||
int c, blank;
|
int c, blank;
|
||||||
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 (is_error()) goto rlcleanup;
|
if (is_error())
|
||||||
pbuf = newbuffer(sizeof (char *));
|
goto rlcleanup;
|
||||||
if (is_error()) goto rlcleanup;
|
pbuf = newbuffer(sizeof(char *));
|
||||||
|
if (is_error())
|
||||||
|
goto rlcleanup;
|
||||||
|
|
||||||
for (blank = 1; ; ) {
|
for (blank = 1;;)
|
||||||
|
{
|
||||||
c = getchar();
|
c = getchar();
|
||||||
if (c == EOF) break;
|
if (c == EOF)
|
||||||
if (c == '\n') {
|
break;
|
||||||
if (blank) {
|
if (c == '\n')
|
||||||
ungetc(c,stdin);
|
{
|
||||||
|
if (blank)
|
||||||
|
{
|
||||||
|
ungetc(c, stdin);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
additem(cbuf, &nullchar);
|
additem(cbuf, &nullchar);
|
||||||
if (is_error()) goto rlcleanup;
|
if (is_error())
|
||||||
|
goto rlcleanup;
|
||||||
ln = copyitems(cbuf);
|
ln = copyitems(cbuf);
|
||||||
if (is_error()) goto rlcleanup;
|
if (is_error())
|
||||||
|
goto rlcleanup;
|
||||||
additem(pbuf, &ln);
|
additem(pbuf, &ln);
|
||||||
if (is_error()) goto rlcleanup;
|
if (is_error())
|
||||||
|
goto rlcleanup;
|
||||||
clearbuffer(cbuf);
|
clearbuffer(cbuf);
|
||||||
blank = 1;
|
blank = 1;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
if (!isspace(c)) blank = 0;
|
{
|
||||||
|
if (!isspace(c))
|
||||||
|
blank = 0;
|
||||||
ch = c;
|
ch = c;
|
||||||
additem(cbuf, &ch);
|
additem(cbuf, &ch);
|
||||||
if (is_error()) goto rlcleanup;
|
if (is_error())
|
||||||
|
goto rlcleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!blank) {
|
if (!blank)
|
||||||
|
{
|
||||||
additem(cbuf, &nullchar);
|
additem(cbuf, &nullchar);
|
||||||
if (is_error()) goto rlcleanup;
|
if (is_error())
|
||||||
|
goto rlcleanup;
|
||||||
ln = copyitems(cbuf);
|
ln = copyitems(cbuf);
|
||||||
if (is_error()) goto rlcleanup;
|
if (is_error())
|
||||||
|
goto rlcleanup;
|
||||||
additem(pbuf, &ln);
|
additem(pbuf, &ln);
|
||||||
if (is_error()) goto rlcleanup;
|
if (is_error())
|
||||||
|
goto rlcleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
additem(pbuf, &nullline);
|
additem(pbuf, &nullline);
|
||||||
if (is_error()) goto rlcleanup;
|
if (is_error())
|
||||||
|
goto rlcleanup;
|
||||||
lines = copyitems(pbuf);
|
lines = copyitems(pbuf);
|
||||||
|
|
||||||
rlcleanup:
|
rlcleanup:
|
||||||
|
|
||||||
if (cbuf) freebuffer(cbuf);
|
if (cbuf)
|
||||||
if (pbuf) {
|
freebuffer(cbuf);
|
||||||
if (!lines) {
|
if (pbuf)
|
||||||
for (;;) {
|
{
|
||||||
|
if (!lines)
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
lines = nextitem(pbuf);
|
lines = nextitem(pbuf);
|
||||||
if (!lines) break;
|
if (!lines)
|
||||||
|
break;
|
||||||
free(*lines);
|
free(*lines);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,35 +244,42 @@ rlcleanup:
|
||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void setdefaults(
|
static void setdefaults(
|
||||||
const char * const *inlines, int *pwidth, int *pprefix,
|
const char *const *inlines, int *pwidth, int *pprefix,
|
||||||
int *psuffix, int *phang, int *plast, int *pmin
|
int *psuffix, int *phang, int *plast, int *pmin)
|
||||||
)
|
|
||||||
/* If any of *pwidth, *pprefix, *psuffix, *phang, *plast, *pmin are */
|
/* If any of *pwidth, *pprefix, *psuffix, *phang, *plast, *pmin are */
|
||||||
/* less than 0, sets them to default values based on inlines, according */
|
/* less than 0, sets them to default values based on inlines, according */
|
||||||
/* to "par.doc". Does not use errmsg because it always succeeds. */
|
/* to "par.doc". Does not use errmsg because it always succeeds. */
|
||||||
{
|
{
|
||||||
int numlines;
|
int numlines;
|
||||||
const char *start, *end, * const *line, *p1, *p2;
|
const char *start, *end, *const *line, *p1, *p2;
|
||||||
|
|
||||||
if (*pwidth < 0) *pwidth = 72;
|
if (*pwidth < 0)
|
||||||
if (*phang < 0) *phang = 0;
|
*pwidth = 72;
|
||||||
if (*plast < 0) *plast = 0;
|
if (*phang < 0)
|
||||||
if (*pmin < 0) *pmin = *plast;
|
*phang = 0;
|
||||||
|
if (*plast < 0)
|
||||||
|
*plast = 0;
|
||||||
|
if (*pmin < 0)
|
||||||
|
*pmin = *plast;
|
||||||
|
|
||||||
for (line = inlines; *line; ++line);
|
for (line = inlines; *line; ++line)
|
||||||
|
;
|
||||||
numlines = line - inlines;
|
numlines = line - inlines;
|
||||||
|
|
||||||
if (*pprefix < 0)
|
if (*pprefix < 0)
|
||||||
{
|
{
|
||||||
if (numlines <= *phang + 1)
|
if (numlines <= *phang + 1)
|
||||||
*pprefix = 0;
|
*pprefix = 0;
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
start = inlines[*phang];
|
start = inlines[*phang];
|
||||||
for (end = start; *end; ++end);
|
for (end = start; *end; ++end)
|
||||||
for (line = inlines + *phang + 1; *line; ++line) {
|
;
|
||||||
for (p1 = start, p2 = *line; p1 < end && *p1 == *p2; ++p1, ++p2);
|
for (line = inlines + *phang + 1; *line; ++line)
|
||||||
|
{
|
||||||
|
for (p1 = start, p2 = *line; p1 < end && *p1 == *p2; ++p1, ++p2)
|
||||||
|
;
|
||||||
end = p1;
|
end = p1;
|
||||||
}
|
}
|
||||||
*pprefix = end - start;
|
*pprefix = end - start;
|
||||||
|
@ -246,99 +290,300 @@ static void setdefaults(
|
||||||
{
|
{
|
||||||
if (numlines <= 1)
|
if (numlines <= 1)
|
||||||
*psuffix = 0;
|
*psuffix = 0;
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
start = *inlines;
|
start = *inlines;
|
||||||
for (end = start; *end; ++end);
|
for (end = start; *end; ++end)
|
||||||
for (line = inlines + 1; *line; ++line) {
|
;
|
||||||
for (p2 = *line; *p2; ++p2);
|
for (line = inlines + 1; *line; ++line)
|
||||||
|
{
|
||||||
|
for (p2 = *line; *p2; ++p2)
|
||||||
|
;
|
||||||
for (p1 = end;
|
for (p1 = end;
|
||||||
p1 > start && p2 > *line && p1[-1] == p2[-1];
|
p1 > start && p2 > *line && p1[-1] == p2[-1];
|
||||||
--p1, --p2);
|
--p1, --p2)
|
||||||
|
;
|
||||||
start = p1;
|
start = p1;
|
||||||
}
|
}
|
||||||
while (end - start >= 2 && isspace(*start) && isspace(start[1])) ++start;
|
while (end - start >= 2 && isspace(*start) && isspace(start[1]))
|
||||||
|
++start;
|
||||||
*psuffix = end - start;
|
*psuffix = end - start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void freelines(char **lines)
|
static void freelines(char **lines)
|
||||||
/* Frees the strings pointed to in the NULL-terminated array lines, then */
|
/* Frees the strings pointed to in the NULL-terminated array lines, then */
|
||||||
/* frees the array. Does not use errmsg because it always succeeds. */
|
/* frees the array. Does not use errmsg because it always succeeds. */
|
||||||
{
|
{
|
||||||
char **line;
|
char **line;
|
||||||
|
|
||||||
for (line = lines; *line; ++line)
|
for (line = lines; *line; ++line)
|
||||||
free(*line);
|
free(*line);
|
||||||
|
|
||||||
free(lines);
|
free(lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int setValue(int *val, char *arg, char *name)
|
||||||
|
{
|
||||||
|
FILE *stream;
|
||||||
|
char *buf;
|
||||||
|
size_t len;
|
||||||
|
if (!arg)
|
||||||
|
{
|
||||||
|
stream = open_memstream(&buf, &len);
|
||||||
|
fprintf(stream, "Require value for argument %s", name);
|
||||||
|
fflush(stream);
|
||||||
|
set_error(buf);
|
||||||
|
fclose(stream);
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
int original_main(int argc, const char * const *argv)
|
// if (*val != -1)
|
||||||
|
// {
|
||||||
|
// stream = open_memstream(&buf, &len);
|
||||||
|
// fprintf(stream, "Multiple input for argument %s", name);
|
||||||
|
// fflush(stream);
|
||||||
|
// set_error(buf);
|
||||||
|
// fclose(stream);
|
||||||
|
// free(buf);
|
||||||
|
// return 0;
|
||||||
|
// }
|
||||||
|
if (!strtoudec(arg, val))
|
||||||
|
{
|
||||||
|
stream = open_memstream(&buf, &len);
|
||||||
|
fprintf(stream, "Invalid Input %s\n", arg);
|
||||||
|
fflush(stream);
|
||||||
|
set_error(buf);
|
||||||
|
fclose(stream);
|
||||||
|
free(buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int setOptions(int argc, char **argv, int *widthbak, int *prefixbak, int *suffixbak, int * hangbak, int *lastbak, int *minbak)
|
||||||
|
{
|
||||||
|
FILE *stream;
|
||||||
|
char *buf;
|
||||||
|
size_t len;
|
||||||
|
int option_index = 0;
|
||||||
|
static struct option long_options[] = {
|
||||||
|
{"version", no_argument, 0, 'v'},
|
||||||
|
{"width", required_argument, 0, 'w'},
|
||||||
|
{"prefix", required_argument, 0, 'p'},
|
||||||
|
{"suffix", required_argument, 0, 's'},
|
||||||
|
{"hang", optional_argument, 0, 'h'},
|
||||||
|
{"last", no_argument, 0, 'L'},
|
||||||
|
{"no-last", no_argument, 0, 'n'},
|
||||||
|
{"min", no_argument, 0, 'M'},
|
||||||
|
{"no-min", no_argument, 0, 'N'},
|
||||||
|
{0, 0, 0, 0}};
|
||||||
|
|
||||||
|
for (char ch = getopt_long(argc, argv, "w:p:s:h::l:m:", long_options, &option_index); ch != -1; ch = getopt_long(argc, argv, "w:p:s:h::l:m:", long_options, &option_index))
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case 'v':
|
||||||
|
stream = open_memstream(&buf, &len);
|
||||||
|
fprintf(stream, "%s %s\n", progname, version);
|
||||||
|
fflush(stream);
|
||||||
|
set_error(buf);
|
||||||
|
fclose(stream);
|
||||||
|
free(buf);
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
case 'W':
|
||||||
|
if (!setValue(widthbak, optarg, "width"))
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
if (!setValue(widthbak, optarg, "width"))
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
if (!setValue(prefixbak, optarg, "prefix"))
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
if (!setValue(suffixbak, optarg, "suffix"))
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
if (!optarg)
|
||||||
|
{
|
||||||
|
optarg = "1";
|
||||||
|
}
|
||||||
|
if (!setValue(hangbak, optarg, "hang"))
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
if (!setValue(lastbak, optarg, "last"))
|
||||||
|
return 0;
|
||||||
|
if (*lastbak != 0 && *lastbak != 1)
|
||||||
|
{
|
||||||
|
stream = open_memstream(&buf, &len);
|
||||||
|
fprintf(stream, "Value for -l must be 0 or 1");
|
||||||
|
fflush(stream);
|
||||||
|
set_error(buf);
|
||||||
|
fclose(stream);
|
||||||
|
free(buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
if (!setValue(minbak, optarg, "last"))
|
||||||
|
return 0;
|
||||||
|
if (*minbak != 0 && *minbak != 1)
|
||||||
|
{
|
||||||
|
stream = open_memstream(&buf, &len);
|
||||||
|
fprintf(stream, "Value for -m must be 0 or 1");
|
||||||
|
fflush(stream);
|
||||||
|
set_error(buf);
|
||||||
|
fclose(stream);
|
||||||
|
free(buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'L':
|
||||||
|
if (!setValue(lastbak, "1", "last"))
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
if (!setValue(lastbak, "0", "last"))
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
case 'M':
|
||||||
|
if (!setValue(minbak, "1", "min"))
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
case 'N':
|
||||||
|
if (!setValue(minbak, "0", "last"))
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int original_main(int argc, const char *const *argv)
|
||||||
{
|
{
|
||||||
int width, widthbak = -1, prefix, prefixbak = -1, suffix, suffixbak = -1,
|
int width, widthbak = -1, prefix, prefixbak = -1, suffix, suffixbak = -1,
|
||||||
hang, hangbak = -1, last, lastbak = -1, min, minbak = -1, c;
|
hang, hangbak = -1, last, lastbak = -1, min, minbak = -1, c, argc_env;
|
||||||
char *parinit, *picopy = NULL, *opt, **inlines = NULL, **outlines = NULL,
|
char *parinit, *picopy = NULL, *opt, **inlines = NULL, **outlines = NULL,
|
||||||
**line;
|
**line, **argv_env, *tmp;
|
||||||
const char * const whitechars = " \f\n\r\t\v";
|
const char *const whitechars = " \f\n\r\t\v";
|
||||||
|
|
||||||
|
// parinit = getenv("PARINIT");
|
||||||
|
// if (parinit) {
|
||||||
|
// picopy = malloc((strlen(parinit) + 1) * sizeof (char));
|
||||||
|
// if (!picopy) {
|
||||||
|
// set_error(outofmem);
|
||||||
|
// goto parcleanup;
|
||||||
|
// }
|
||||||
|
// strcpy(picopy,parinit);
|
||||||
|
// opt = strtok(picopy,whitechars);
|
||||||
|
// while (opt) {
|
||||||
|
// parseopt(opt, &widthbak, &prefixbak,
|
||||||
|
// &suffixbak, &hangbak, &lastbak, &minbak);
|
||||||
|
// if (is_error()) goto parcleanup;
|
||||||
|
// opt = strtok(NULL,whitechars);
|
||||||
|
// }
|
||||||
|
// free(picopy);
|
||||||
|
// picopy = NULL;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// while (*++argv) {
|
||||||
|
// parseopt(*argv, &widthbak, &prefixbak,
|
||||||
|
// &suffixbak, &hangbak, &lastbak, &minbak);
|
||||||
|
// if (is_error()) goto parcleanup;
|
||||||
|
// }
|
||||||
|
|
||||||
parinit = getenv("PARINIT");
|
parinit = getenv("PARINIT");
|
||||||
if (parinit) {
|
if (parinit)
|
||||||
|
{
|
||||||
picopy = malloc((strlen(parinit) + 1) * sizeof (char));
|
picopy = malloc((strlen(parinit) + 1) * sizeof (char));
|
||||||
if (!picopy) {
|
if (!picopy) {
|
||||||
set_error(outofmem);
|
set_error(outofmem);
|
||||||
goto parcleanup;
|
goto parcleanup;
|
||||||
}
|
}
|
||||||
|
argc_env = 1;
|
||||||
|
argv_env = malloc((argc_env) * sizeof (char*));
|
||||||
|
argv_env[0] = malloc((strlen(argv[0])+1) * sizeof(char));
|
||||||
|
tmp = argv_env[0];
|
||||||
|
strcpy(tmp, argv[0]);
|
||||||
strcpy(picopy,parinit);
|
strcpy(picopy,parinit);
|
||||||
opt = strtok(picopy,whitechars);
|
opt = strtok(picopy,whitechars);
|
||||||
while (opt) {
|
while (opt) {
|
||||||
parseopt(opt, &widthbak, &prefixbak,
|
argc_env ++;
|
||||||
&suffixbak, &hangbak, &lastbak, &minbak);
|
argv_env = realloc(argv_env, (argc_env + 1)*sizeof(char*));
|
||||||
if (is_error()) goto parcleanup;
|
argv_env[argc_env-1] = malloc((strlen(opt)+1)*sizeof(char));
|
||||||
|
tmp = argv_env[argc_env-1];
|
||||||
|
strcpy(tmp, opt);
|
||||||
opt = strtok(NULL,whitechars);
|
opt = strtok(NULL,whitechars);
|
||||||
}
|
}
|
||||||
free(picopy);
|
argv_env = realloc(argv_env, (argc_env + 1)*sizeof(char*));
|
||||||
picopy = NULL;
|
argv_env[argc_env] = NULL;
|
||||||
}
|
|
||||||
|
|
||||||
while (*++argv) {
|
for (size_t i = 0; i < argc_env; i++)
|
||||||
parseopt(*argv, &widthbak, &prefixbak,
|
{
|
||||||
&suffixbak, &hangbak, &lastbak, &minbak);
|
printf("%s\n", argv_env[i]);
|
||||||
if (is_error()) goto parcleanup;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (;;) {
|
if (!setOptions(argc_env, (char **)argv_env, &widthbak, &prefixbak, &suffixbak, &hangbak, &lastbak, &minbak))
|
||||||
for (;;) {
|
goto parcleanup;
|
||||||
|
freelines(argv_env);
|
||||||
|
}
|
||||||
|
if (!setOptions(argc, (char **)argv, &widthbak, &prefixbak, &suffixbak, &hangbak, &lastbak, &minbak))
|
||||||
|
goto parcleanup;
|
||||||
|
|
||||||
|
printf("width: %d, prefix: %d, suffix: %d, hang: %d, last: %d, min: %d", widthbak, prefixbak, suffixbak, hangbak, lastbak, minbak);
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
c = getchar();
|
c = getchar();
|
||||||
if (c == EOF) goto parcleanup;
|
if (c == EOF)
|
||||||
if (c != '\n') break;
|
goto parcleanup;
|
||||||
|
if (c != '\n')
|
||||||
|
break;
|
||||||
putchar(c);
|
putchar(c);
|
||||||
}
|
}
|
||||||
ungetc(c,stdin);
|
ungetc(c, stdin);
|
||||||
|
|
||||||
inlines = readlines();
|
inlines = readlines();
|
||||||
if (is_error()) goto parcleanup;
|
if (is_error())
|
||||||
if (!*inlines) {
|
goto parcleanup;
|
||||||
|
if (!*inlines)
|
||||||
|
{
|
||||||
free(inlines);
|
free(inlines);
|
||||||
inlines = NULL;
|
inlines = NULL;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
width = widthbak; prefix = prefixbak; suffix = suffixbak;
|
width = widthbak;
|
||||||
hang = hangbak; last = lastbak; min = minbak;
|
prefix = prefixbak;
|
||||||
setdefaults((const char * const *) inlines,
|
suffix = suffixbak;
|
||||||
|
hang = hangbak;
|
||||||
|
last = lastbak;
|
||||||
|
min = minbak;
|
||||||
|
setdefaults((const char *const *)inlines,
|
||||||
&width, &prefix, &suffix, &hang, &last, &min);
|
&width, &prefix, &suffix, &hang, &last, &min);
|
||||||
|
|
||||||
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 (is_error()) goto parcleanup;
|
if (is_error())
|
||||||
|
goto parcleanup;
|
||||||
|
|
||||||
freelines(inlines);
|
freelines(inlines);
|
||||||
inlines = NULL;
|
inlines = NULL;
|
||||||
|
|
||||||
for (line = outlines; *line; ++line)
|
for (line = outlines; *line; ++line)
|
||||||
puts(*line);
|
puts(*line);
|
||||||
|
|
||||||
freelines(outlines);
|
freelines(outlines);
|
||||||
|
@ -347,15 +592,19 @@ int original_main(int argc, const char * const *argv)
|
||||||
|
|
||||||
parcleanup:
|
parcleanup:
|
||||||
|
|
||||||
if (picopy) free(picopy);
|
if (picopy)
|
||||||
if (inlines) freelines(inlines);
|
free(picopy);
|
||||||
if (outlines) freelines(outlines);
|
if (inlines)
|
||||||
|
freelines(inlines);
|
||||||
|
if (outlines)
|
||||||
|
freelines(outlines);
|
||||||
|
|
||||||
if (is_error()) {
|
if (is_error())
|
||||||
|
{
|
||||||
report_error(stderr);
|
report_error(stderr);
|
||||||
clear_error();
|
clear_error();
|
||||||
return(EXIT_FAILURE);
|
return (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return(EXIT_SUCCESS);
|
return (EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ Test(base_suite, basic_test) {
|
||||||
*/
|
*/
|
||||||
Test(base_suite, prefix_suffix_test) {
|
Test(base_suite, prefix_suffix_test) {
|
||||||
char *name = "prefix_suffix";
|
char *name = "prefix_suffix";
|
||||||
sprintf(program_options, "%s", "w80");
|
sprintf(program_options, "%s", "-w 80");
|
||||||
int err = run_using_system(name, "", "", STANDARD_LIMITS);
|
int err = run_using_system(name, "", "", STANDARD_LIMITS);
|
||||||
assert_expected_status(EXIT_SUCCESS, err);
|
assert_expected_status(EXIT_SUCCESS, err);
|
||||||
assert_outfile_matches(name, NULL);
|
assert_outfile_matches(name, NULL);
|
||||||
|
@ -62,7 +62,7 @@ Test(base_suite, valgrind_leak_test) {
|
||||||
*/
|
*/
|
||||||
Test(base_suite, valgrind_uninitialized_test) {
|
Test(base_suite, valgrind_uninitialized_test) {
|
||||||
char *name = "valgrind_uninitialized";
|
char *name = "valgrind_uninitialized";
|
||||||
sprintf(program_options, "%s", "p10 s10");
|
sprintf(program_options, "%s", "-p 10 -s 10");
|
||||||
int err = run_using_system(name, "", "valgrind --leak-check=no --undef-value-errors=yes --error-exitcode=37", STANDARD_LIMITS);
|
int err = run_using_system(name, "", "valgrind --leak-check=no --undef-value-errors=yes --error-exitcode=37", STANDARD_LIMITS);
|
||||||
assert_no_valgrind_errors(err);
|
assert_no_valgrind_errors(err);
|
||||||
assert_expected_status(0x1, err);
|
assert_expected_status(0x1, err);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user