4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 1995 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
44 #define USAGE "usage: nl [-p] [-b type] [-d delim] [ -f type] " \
45 "[-h type] [-i incr] [-l num] [-n format]\n" \
46 "[-s sep] [-v startnum] [-w width] [file]\n"
48 #define USAGE "usage: nl [-p] [-btype] [-ddelim] [ -ftype] " \
49 "[-htype] [-iincr] [-lnum] [-nformat] [-ssep] " \
50 "[-vstartnum] [-wwidth] [file]\n"
54 int nbra
, sed
; /* u370 - not used in nl.c, but extern in regexp.h */
56 static int width
= 6; /* Declare default width of number */
57 static char nbuf
[100]; /* Declare bufsize used in convert/pad/cnt routines */
58 static char *bexpbuf
; /* Declare the regexp buf */
59 static char *hexpbuf
; /* Declare the regexp buf */
60 static char *fexpbuf
; /* Declare the regexp buf */
61 static char delim1
= '\\';
62 static char delim2
= ':'; /* Default delimiters. */
63 static char pad
= ' '; /* Declare the default pad for numbers */
64 static char *s
; /* Declare the temp array for args */
65 static char s1
[EXPSIZ
]; /* Declare the conversion array */
66 static char format
= 'n'; /* Declare the format of numbers to be rt just */
67 static int q
= 2; /* Initialize arg pointer to drop 1st 2 chars */
68 static int k
; /* Declare var for return of convert */
69 static int r
; /* Declare the arg array ptr for string args */
72 static int convert(int, char *);
74 static int convert(char *);
76 static void num(int, int);
77 static void npad(int, char *);
79 static void optmsg(int, char *);
81 static void optmsg(char *);
83 static void pnum(int, char *);
84 static void regerr(int);
87 extern char *optarg
; /* getopt support */
91 main(int argc
, char *argv
[])
96 register char header
= 'n';
97 register char body
= 't';
98 register char footer
= 'n';
100 char tempchr
; /* Temporary holding variable. */
104 int cnt
; /* line counter */
105 int pass1
= 1; /* First pass flag. 1=pass1, 0=additional passes. */
124 (void) setlocale(LC_ALL
, "");
125 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
126 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
128 (void) textdomain(TEXT_DOMAIN
);
132 * XPG4: Allow either a space or no space between the
133 * options and their required arguments.
137 while ((c
= getopt(argc
, argv
,
138 "pb:d:f:h:i:l:n:s:v:w:")) != EOF
) {
153 (void) strcpy(pat
, optarg
+1);
156 compile(pat
, NULL
, NULL
);
179 (void) strcpy(pat
, optarg
+1);
182 compile(pat
, NULL
, NULL
);
205 (void) strcpy(pat
, optarg
+1);
208 compile(pat
, NULL
, NULL
);
220 if (optarg
== (char *)NULL
)
229 startcnt
= convert(c
, optarg
);
235 increment
= convert(c
, optarg
);
241 width
= convert(c
, optarg
);
247 blank
= convert(c
, optarg
);
252 if (*(optarg
+1) == 'n')
258 if ((*(optarg
+1) == 'n') ||
259 (*(optarg
+1) == 'z'))
260 format
= *(optarg
+1);
273 (void) strcpy(sep
, optarg
);
278 if (*(optarg
+1) == '\0')
280 delim2
= *(optarg
+1);
281 if (*(optarg
+2) != '\0')
286 } /* end switch char returned from getopt() */
287 } /* end while getopt */
294 if ((iptr
= fopen(argv
[0], "r")) == NULL
) {
295 (void) fprintf(stderr
, "nl: %s: ", argv
[0]);
302 } /* end while argc > 0 */
303 /* end XPG4 version of argument parsing */
306 * Solaris: For backward compatibility, do not allow a space between the
307 * options and their arguments. Option arguments are optional,
308 * not required as in the XPG4 version of nl.
310 for (j
= 1; j
< argc
; j
++) {
311 if (argv
[j
][i
] == '-' && (c
= argv
[j
][i
+ 1])) {
315 switch (argv
[j
][i
+ 2]) {
329 while (s
[q
] != '\0') {
337 compile(pat
, NULL
, NULL
);
349 switch (argv
[j
][i
+ 2]) {
363 while (s
[q
] != '\0') {
371 compile(pat
, NULL
, NULL
);
383 switch (argv
[j
][i
+ 2]) {
397 while (s
[q
] != '\0') {
405 compile(pat
, NULL
, NULL
);
417 if (argv
[j
][i
+2] == '\0')
425 if (argv
[j
][i
+2] == '\0')
428 startcnt
= convert(argv
[j
]);
431 if (argv
[j
][i
+2] == '\0')
434 increment
= convert(argv
[j
]);
437 if (argv
[j
][i
+2] == '\0')
440 width
= convert(argv
[j
]);
443 if (argv
[j
][i
+2] == '\0')
446 blank
= convert(argv
[j
]);
449 switch (argv
[j
][i
+2]) {
451 if (argv
[j
][i
+3] == 'n')
459 if ((argv
[j
][i
+3] == 'n') ||
460 (argv
[j
][i
+3] == 'z'))
461 format
= argv
[j
][i
+3];
476 if (argv
[j
][i
+ 2] != '\0') {
480 while (s
[q
] != '\0') {
487 /* else default sep is tab (set above) */
490 tempchr
= argv
[j
][i
+2];
491 if (tempchr
== '\0')break;
494 tempchr
= argv
[j
][i
+3];
495 if (tempchr
== '\0')break;
497 if (argv
[j
][i
+4] != '\0')optmsg(argv
[j
]);
500 if (argv
[j
][i
+ 2] == '\0') {
508 } else if ((iptr
= fopen(argv
[j
], "r")) == NULL
) {
509 /* end of options, filename starting with '-' */
510 (void) fprintf(stderr
, "nl: %s: ", argv
[j
]);
514 } else if ((iptr
= fopen(argv
[j
], "r")) == NULL
) {
515 /* filename starting with char other than '-' */
516 (void) fprintf(stderr
, "nl: %s: ", argv
[j
]);
520 } /* closing brace of for loop */
521 /* end Solaris version of argument parsing */
524 /* ON FIRST PASS ONLY, SET LINE COUNTER (cnt) = startcnt & */
525 /* SET DEFAULT BODY TYPE TO NUMBER ALL LINES. */
534 * DO WHILE THERE IS INPUT
535 * CHECK TO SEE IF LINE IS NUMBERED,
536 * IF SO, CALCULATE NUM, PRINT NUM,
537 * THEN OUTPUT SEPERATOR CHAR AND LINE
540 while ((p
= fgets(line
, sizeof (line
), iptr
)) != NULL
) {
541 if (p
[0] == delim1
&& p
[1] == delim2
) {
542 if (p
[2] == delim1
&&
553 if (p
[2] == delim1
&& p
[3] == delim2
&& p
[4] == '\n') {
554 if (cntck
!= 'y' && last
!= 'h')
560 if (p
[0] == delim1
&& p
[1] == delim2
&&
562 if (cntck
!= 'y' && last
== 'f')
573 if (p
[lnt
-1] == '\n')
579 (void) fprintf(optr
, "\n");
587 * XPG4: The wording of Spec 1170 is misleading;
588 * the official interpretation is to number all
589 * non-empty lines, ie: the Solaris code has not
602 if (blank
== blankctr
) {
615 if (step(p
, bexpbuf
)) {
623 if (step(p
, hexpbuf
)) {
631 if (step(p
, fexpbuf
)) {
641 (void) fprintf(optr
, "%s", line
);
643 } /* Closing brace of "else" */
644 } /* Closing brace of "while". */
650 /* REGEXP ERR ROUTINE */
655 (void) fprintf(stderr
, gettext(
656 "nl: invalid regular expression: error code %d\n"), c
);
660 /* CALCULATE NUMBER ROUTINE */
663 pnum(int n
, char *sep
)
670 for (i
= 0; i
< width
; i
++)
674 while (nbuf
[0] == ' ') {
675 for (i
= 0; i
< width
; i
++)
680 (void) printf("%s%s", nbuf
, sep
);
683 /* IF NUM > 10, THEN USE THIS CALCULATE ROUTINE */
691 nbuf
[p
] = (v
% 10) + '0';
697 /* CONVERT ARG STRINGS TO STRING ARRAYS */
701 convert(int c
, char *option_arg
)
705 while (s
[q
] != '\0') {
706 if (s
[q
] >= '0' && s
[q
] <= '9') {
711 optmsg(c
, option_arg
);
718 /* Solaris version */
725 while (s
[q
] != '\0') {
726 if (s
[q
] >= '0' && s
[q
] <= '9') {
740 /* CALCULATE NUM/TEXT SEPRATOR */
743 npad(int width
, char *sep
)
748 for (i
= 0; i
< width
; i
++)
750 (void) printf("%s", nbuf
);
752 for (i
= 0; i
< (int)strlen(sep
); i
++)
758 optmsg(int option
, char *option_arg
)
760 if (option_arg
!= (char *)NULL
) {
761 (void) fprintf(stderr
, gettext(
762 "nl: invalid option (-%c %s)\n"), option
, option_arg
);
764 /* else getopt() will print illegal option message */
768 /* Solaris version */
772 (void) fprintf(stderr
, gettext("nl: invalid option (%s)\n"), option
);
780 (void) fprintf(stderr
, gettext(USAGE
));