#include <locale.h>
#include <regexpr.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <wchar.h>
#include <wctype.h>
#include <limits.h>
#define EXPSIZ 512
#ifdef XPG4
#define USAGE "usage: nl [-p] [-b type] [-d delim] [ -f type] " \
"[-h type] [-i incr] [-l num] [-n format]\n" \
"[-s sep] [-v startnum] [-w width] [file]\n"
#else
#define USAGE "usage: nl [-p] [-btype] [-ddelim] [ -ftype] " \
"[-htype] [-iincr] [-lnum] [-nformat] [-ssep] " \
"[-vstartnum] [-wwidth] [file]\n"
#endif
#ifdef u370
int nbra, sed;
#endif
static int width = 6;
static char nbuf[100];
static char *bexpbuf;
static char *hexpbuf;
static char *fexpbuf;
static char delim1 = '\\';
static char delim2 = ':';
static char pad = ' ';
static char *s;
static char s1[EXPSIZ];
static char format = 'n';
static int q = 2;
static int k;
static int r;
#ifdef XPG4
static int convert(int, char *);
#else
static int convert(char *);
#endif
static void num(int, int);
static void npad(int, char *);
#ifdef XPG4
static void optmsg(int, char *);
#else
static void optmsg(char *);
#endif
static void pnum(int, char *);
static void regerr(int);
static void usage();
extern char *optarg;
extern int optind;
int
main(int argc, char *argv[])
{
register int j;
register int i = 0;
register char *p;
register char header = 'n';
register char body = 't';
register char footer = 'n';
char line[LINE_MAX];
char tempchr;
char swtch = 'n';
char cntck = 'n';
char type;
int cnt;
int pass1 = 1;
char sep[EXPSIZ];
char pat[EXPSIZ];
int startcnt = 1;
int increment = 1;
int blank = 1;
int blankctr = 0;
int c;
int lnt;
char last;
FILE *iptr = stdin;
FILE *optr = stdout;
#ifndef XPG4
int option_end = 0;
#endif
sep[0] = '\t';
sep[1] = '\0';
(void) setlocale(LC_ALL, "");
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
(void) textdomain(TEXT_DOMAIN);
#ifdef XPG4
while (argc > 0) {
while ((c = getopt(argc, argv,
"pb:d:f:h:i:l:n:s:v:w:")) != EOF) {
switch (c) {
case 'h':
switch (*optarg) {
case 'n':
header = 'n';
break;
case 't':
header = 't';
break;
case 'a':
header = 'a';
break;
case 'p':
(void) strcpy(pat, optarg+1);
header = 'h';
hexpbuf =
compile(pat, NULL, NULL);
if (regerrno)
regerr(regerrno);
break;
case '\0':
header = 'n';
break;
default:
optmsg(c, optarg);
}
break;
case 'b':
switch (*optarg) {
case 't':
body = 't';
break;
case 'a':
body = 'a';
break;
case 'n':
body = 'n';
break;
case 'p':
(void) strcpy(pat, optarg+1);
body = 'b';
bexpbuf =
compile(pat, NULL, NULL);
if (regerrno)
regerr(regerrno);
break;
case '\0':
body = 't';
break;
default:
optmsg(c, optarg);
}
break;
case 'f':
switch (*optarg) {
case 'n':
footer = 'n';
break;
case 't':
footer = 't';
break;
case 'a':
footer = 'a';
break;
case 'p':
(void) strcpy(pat, optarg+1);
footer = 'f';
fexpbuf =
compile(pat, NULL, NULL);
if (regerrno)
regerr(regerrno);
break;
case '\0':
footer = 'n';
break;
default:
optmsg(c, optarg);
}
break;
case 'p':
if (optarg == (char *)NULL)
cntck = 'y';
else
optmsg(c, optarg);
break;
case 'v':
if (*optarg == '\0')
startcnt = 1;
else
startcnt = convert(c, optarg);
break;
case 'i':
if (*optarg == '\0')
increment = 1;
else
increment = convert(c, optarg);
break;
case 'w':
if (*optarg == '\0')
width = 6;
else
width = convert(c, optarg);
break;
case 'l':
if (*optarg == '\0')
blank = 1;
else
blank = convert(c, optarg);
break;
case 'n':
switch (*optarg) {
case 'l':
if (*(optarg+1) == 'n')
format = 'l';
else
optmsg(c, optarg);
break;
case 'r':
if ((*(optarg+1) == 'n') ||
(*(optarg+1) == 'z'))
format = *(optarg+1);
else
optmsg(c, optarg);
break;
case '\0':
format = 'n';
break;
default:
optmsg(c, optarg);
break;
}
break;
case 's':
(void) strcpy(sep, optarg);
break;
case 'd':
delim1 = *optarg;
if (*(optarg+1) == '\0')
break;
delim2 = *(optarg+1);
if (*(optarg+2) != '\0')
optmsg(c, optarg);
break;
default:
optmsg(c, optarg);
}
}
argv += optind;
argc -= optind;
optind = 0;
if (argc > 0) {
if ((iptr = fopen(argv[0], "r")) == NULL) {
(void) fprintf(stderr, "nl: %s: ", argv[0]);
perror("");
return (1);
}
++argv;
--argc;
}
}
#else
for (j = 1; j < argc; j++) {
if (argv[j][i] == '-' && (c = argv[j][i + 1])) {
if (!option_end) {
switch (c) {
case 'h':
switch (argv[j][i + 2]) {
case 'n':
header = 'n';
break;
case 't':
header = 't';
break;
case 'a':
header = 'a';
break;
case 'p':
s = argv[j];
q = 3;
r = 0;
while (s[q] != '\0') {
pat[r] = s[q];
r++;
q++;
}
pat[r] = '\0';
header = 'h';
hexpbuf =
compile(pat, NULL, NULL);
if (regerrno)
regerr(regerrno);
break;
case '\0':
header = 'n';
break;
default:
optmsg(argv[j]);
}
break;
case 'b':
switch (argv[j][i + 2]) {
case 't':
body = 't';
break;
case 'a':
body = 'a';
break;
case 'n':
body = 'n';
break;
case 'p':
s = argv[j];
q = 3;
r = 0;
while (s[q] != '\0') {
pat[r] = s[q];
r++;
q++;
}
pat[r] = '\0';
body = 'b';
bexpbuf =
compile(pat, NULL, NULL);
if (regerrno)
regerr(regerrno);
break;
case '\0':
body = 't';
break;
default:
optmsg(argv[j]);
}
break;
case 'f':
switch (argv[j][i + 2]) {
case 'n':
footer = 'n';
break;
case 't':
footer = 't';
break;
case 'a':
footer = 'a';
break;
case 'p':
s = argv[j];
q = 3;
r = 0;
while (s[q] != '\0') {
pat[r] = s[q];
r++;
q++;
}
pat[r] = '\0';
footer = 'f';
fexpbuf =
compile(pat, NULL, NULL);
if (regerrno)
regerr(regerrno);
break;
case '\0':
footer = 'n';
break;
default:
optmsg(argv[j]);
}
break;
case 'p':
if (argv[j][i+2] == '\0')
cntck = 'y';
else
{
optmsg(argv[j]);
}
break;
case 'v':
if (argv[j][i+2] == '\0')
startcnt = 1;
else
startcnt = convert(argv[j]);
break;
case 'i':
if (argv[j][i+2] == '\0')
increment = 1;
else
increment = convert(argv[j]);
break;
case 'w':
if (argv[j][i+2] == '\0')
width = 6;
else
width = convert(argv[j]);
break;
case 'l':
if (argv[j][i+2] == '\0')
blank = 1;
else
blank = convert(argv[j]);
break;
case 'n':
switch (argv[j][i+2]) {
case 'l':
if (argv[j][i+3] == 'n')
format = 'l';
else
{
optmsg(argv[j]);
}
break;
case 'r':
if ((argv[j][i+3] == 'n') ||
(argv[j][i+3] == 'z'))
format = argv[j][i+3];
else
{
optmsg(argv[j]);
}
break;
case '\0':
format = 'n';
break;
default:
optmsg(argv[j]);
break;
}
break;
case 's':
if (argv[j][i + 2] != '\0') {
s = argv[j];
q = 2;
r = 0;
while (s[q] != '\0') {
sep[r] = s[q];
r++;
q++;
}
sep[r] = '\0';
}
break;
case 'd':
tempchr = argv[j][i+2];
if (tempchr == '\0')break;
delim1 = tempchr;
tempchr = argv[j][i+3];
if (tempchr == '\0')break;
delim2 = tempchr;
if (argv[j][i+4] != '\0')optmsg(argv[j]);
break;
case '-':
if (argv[j][i + 2] == '\0') {
option_end = 1;
break;
}
default:
optmsg(argv[j]);
}
} else if ((iptr = fopen(argv[j], "r")) == NULL) {
(void) fprintf(stderr, "nl: %s: ", argv[j]);
perror("");
return (1);
}
} else if ((iptr = fopen(argv[j], "r")) == NULL) {
(void) fprintf(stderr, "nl: %s: ", argv[j]);
perror("");
return (1);
}
}
#endif
if (pass1) {
cnt = startcnt;
type = body;
last = 'b';
pass1 = 0;
}
while ((p = fgets(line, sizeof (line), iptr)) != NULL) {
if (p[0] == delim1 && p[1] == delim2) {
if (p[2] == delim1 &&
p[3] == delim2 &&
p[4] == delim1 &&
p[5] == delim2 &&
p[6] == '\n') {
if (cntck != 'y')
cnt = startcnt;
type = header;
last = 'h';
swtch = 'y';
} else {
if (p[2] == delim1 && p[3] == delim2 && p[4] == '\n') {
if (cntck != 'y' && last != 'h')
cnt = startcnt;
type = body;
last = 'b';
swtch = 'y';
} else {
if (p[0] == delim1 && p[1] == delim2 &&
p[2] == '\n') {
if (cntck != 'y' && last == 'f')
cnt = startcnt;
type = footer;
last = 'f';
swtch = 'y';
}
}
}
}
if (p[0] != '\n') {
lnt = strlen(p);
if (p[lnt-1] == '\n')
p[lnt-1] = '\0';
}
if (swtch == 'y') {
swtch = 'n';
(void) fprintf(optr, "\n");
} else {
switch (type) {
case 'n':
npad(width, sep);
break;
case 't':
if (p[0] != '\n') {
pnum(cnt, sep);
cnt += increment;
} else {
npad(width, sep);
}
break;
case 'a':
if (p[0] == '\n') {
blankctr++;
if (blank == blankctr) {
blankctr = 0;
pnum(cnt, sep);
cnt += increment;
} else
npad(width, sep);
} else {
blankctr = 0;
pnum(cnt, sep);
cnt += increment;
}
break;
case 'b':
if (step(p, bexpbuf)) {
pnum(cnt, sep);
cnt += increment;
} else {
npad(width, sep);
}
break;
case 'h':
if (step(p, hexpbuf)) {
pnum(cnt, sep);
cnt += increment;
} else {
npad(width, sep);
}
break;
case 'f':
if (step(p, fexpbuf)) {
pnum(cnt, sep);
cnt += increment;
} else {
npad(width, sep);
}
break;
}
if (p[0] != '\n')
p[lnt-1] = '\n';
(void) fprintf(optr, "%s", line);
}
}
(void) fclose(iptr);
return (0);
}
static void
regerr(int c)
{
(void) fprintf(stderr, gettext(
"nl: invalid regular expression: error code %d\n"), c);
exit(1);
}
static void
pnum(int n, char *sep)
{
register int i;
if (format == 'z') {
pad = '0';
}
for (i = 0; i < width; i++)
nbuf[i] = pad;
num(n, width - 1);
if (format == 'l') {
while (nbuf[0] == ' ') {
for (i = 0; i < width; i++)
nbuf[i] = nbuf[i+1];
nbuf[width-1] = ' ';
}
}
(void) printf("%s%s", nbuf, sep);
}
static void
num(int v, int p)
{
if (v < 10)
nbuf[p] = v + '0';
else {
nbuf[p] = (v % 10) + '0';
if (p > 0)
num(v / 10, p - 1);
}
}
#ifdef XPG4
static int
convert(int c, char *option_arg)
{
s = option_arg;
q = r = 0;
while (s[q] != '\0') {
if (s[q] >= '0' && s[q] <= '9') {
s1[r] = s[q];
r++;
q++;
} else
optmsg(c, option_arg);
}
s1[r] = '\0';
k = atoi(s1);
return (k);
}
#else
static int
convert(char *argv)
{
s = (char *)argv;
q = 2;
r = 0;
while (s[q] != '\0') {
if (s[q] >= '0' && s[q] <= '9') {
s1[r] = s[q];
r++;
q++;
} else {
optmsg(argv);
}
}
s1[r] = '\0';
k = atoi(s1);
return (k);
}
#endif
static void
npad(int width, char *sep)
{
register int i;
pad = ' ';
for (i = 0; i < width; i++)
nbuf[i] = pad;
(void) printf("%s", nbuf);
for (i = 0; i < (int)strlen(sep); i++)
(void) printf(" ");
}
#ifdef XPG4
static void
optmsg(int option, char *option_arg)
{
if (option_arg != (char *)NULL) {
(void) fprintf(stderr, gettext(
"nl: invalid option (-%c %s)\n"), option, option_arg);
}
usage();
}
#else
static void
optmsg(char *option)
{
(void) fprintf(stderr, gettext("nl: invalid option (%s)\n"), option);
usage();
}
#endif
void
usage()
{
(void) fprintf(stderr, gettext(USAGE));
exit(1);
}