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
);
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') {
507 } else if ((iptr
= fopen(argv
[j
], "r")) == NULL
) {
508 /* end of options, filename starting with '-' */
509 (void) fprintf(stderr
, "nl: %s: ", argv
[j
]);
513 } else if ((iptr
= fopen(argv
[j
], "r")) == NULL
) {
514 /* filename starting with char other than '-' */
515 (void) fprintf(stderr
, "nl: %s: ", argv
[j
]);
519 } /* closing brace of for loop */
520 /* end Solaris version of argument parsing */
523 /* ON FIRST PASS ONLY, SET LINE COUNTER (cnt) = startcnt & */
524 /* SET DEFAULT BODY TYPE TO NUMBER ALL LINES. */
533 * DO WHILE THERE IS INPUT
534 * CHECK TO SEE IF LINE IS NUMBERED,
535 * IF SO, CALCULATE NUM, PRINT NUM,
536 * THEN OUTPUT SEPERATOR CHAR AND LINE
539 while ((p
= fgets(line
, sizeof (line
), iptr
)) != NULL
) {
540 if (p
[0] == delim1
&& p
[1] == delim2
) {
541 if (p
[2] == delim1
&&
552 if (p
[2] == delim1
&& p
[3] == delim2
&& p
[4] == '\n') {
553 if (cntck
!= 'y' && last
!= 'h')
559 if (p
[0] == delim1
&& p
[1] == delim2
&&
561 if (cntck
!= 'y' && last
== 'f')
572 if (p
[lnt
-1] == '\n')
578 (void) fprintf(optr
, "\n");
586 * XPG4: The wording of Spec 1170 is misleading;
587 * the official interpretation is to number all
588 * non-empty lines, ie: the Solaris code has not
601 if (blank
== blankctr
) {
614 if (step(p
, bexpbuf
)) {
622 if (step(p
, hexpbuf
)) {
630 if (step(p
, fexpbuf
)) {
640 (void) fprintf(optr
, "%s", line
);
642 } /* Closing brace of "else" */
643 } /* Closing brace of "while". */
649 /* REGEXP ERR ROUTINE */
654 (void) fprintf(stderr
, gettext(
655 "nl: invalid regular expression: error code %d\n"), c
);
659 /* CALCULATE NUMBER ROUTINE */
662 pnum(int n
, char *sep
)
669 for (i
= 0; i
< width
; i
++)
673 while (nbuf
[0] == ' ') {
674 for (i
= 0; i
< width
; i
++)
679 (void) printf("%s%s", nbuf
, sep
);
682 /* IF NUM > 10, THEN USE THIS CALCULATE ROUTINE */
690 nbuf
[p
] = (v
% 10) + '0';
696 /* CONVERT ARG STRINGS TO STRING ARRAYS */
700 convert(int c
, char *option_arg
)
704 while (s
[q
] != '\0') {
705 if (s
[q
] >= '0' && s
[q
] <= '9') {
710 optmsg(c
, option_arg
);
717 /* Solaris version */
724 while (s
[q
] != '\0') {
725 if (s
[q
] >= '0' && s
[q
] <= '9') {
739 /* CALCULATE NUM/TEXT SEPRATOR */
742 npad(int width
, char *sep
)
747 for (i
= 0; i
< width
; i
++)
749 (void) printf("%s", nbuf
);
751 for (i
= 0; i
< (int)strlen(sep
); i
++)
757 optmsg(int option
, char *option_arg
)
759 if (option_arg
!= NULL
) {
760 (void) fprintf(stderr
, gettext(
761 "nl: invalid option (-%c %s)\n"), option
, option_arg
);
763 /* else getopt() will print illegal option message */
767 /* Solaris version */
771 (void) fprintf(stderr
, gettext("nl: invalid option (%s)\n"), option
);
779 (void) fprintf(stderr
, gettext(USAGE
));