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 2005 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 */
30 #pragma ident "%Z%%M% %I% %E% SMI"
34 * Function Page Description
35 * append 16 Append chars to end of line.
36 * begtrunc 16 Truncate characters from beginning of line.
37 * center 5 Center text in the work area.
38 * cnvtspec 7 Convert tab spec to tab positions.
39 * endtrunc 16 Truncate chars from end of line.
40 * inputtabs 17 Expand according to input tab specs.
42 * inputn 5 Read a command line option number.
43 * options 4 Process command line options.
44 * outputtabs 19 Contract according to output tab specs.
45 * prepend 16 Prepend chars to line.
46 * process 15 Process one line of input.
47 * readline 14 Read one line from the file.
48 * readspec 12 Read a tabspec from a file.
49 * sstrip 18 Strip SCCS SID char from beginning of line.
50 * sadd 18 Add SCCS SID chars to end of line.
51 * type 14 Determine type of a character.
64 static int tabtbl
[500] = { /* Table containing tab stops */
65 1, 9, 17, 25, 33, 41, 49, 57, 65, 73, 0,
67 1, 10, 16, 36, 72, 0, /* IBM 370 Assembler */
68 1, 10, 16, 40, 72, 0, /* IBM 370 Assembler (alt.) */
69 1, 8, 12, 16, 20, 55, 0, /* COBOL */
70 1, 6, 10, 14, 49, 0, /* COBOL (crunched) */
71 1, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 54, 58, 62, 67, 0,
72 /* COBOL (crunched, many cols.) */
73 1, 7, 11, 15, 19, 23, 0, /* FORTRAN */
74 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 0,
76 1, 10, 55, 0, /* SNOBOL */
77 1, 12, 20, 44, 0 }, /* UNIVAC Assembler */
79 *nexttab
= &tabtbl
[87], /* Pointer to next empty slot */
81 *spectbl
[40] = { /* Table of pointers into tabtbl */
82 &tabtbl
[0], /* Default specification */
83 &tabtbl
[11], /* -a specification */
84 &tabtbl
[17], /* -a2 specification */
85 &tabtbl
[23], /* -c specification */
86 &tabtbl
[30], /* -c2 specification */
87 &tabtbl
[36], /* -c3 specification */
88 &tabtbl
[54], /* -f specification */
89 &tabtbl
[61], /* -p specification */
90 &tabtbl
[78], /* -s specification */
91 &tabtbl
[82] }, /* -u specification */
93 savek
; /* Stores char count stripped from front of line. */
94 static int nextspec
= 10, /* Index to next slot */
95 sitabspec
= -1, /* Index to "standard input" spec. */
96 effll
= 80, /* Effective line length */
97 optionf
= 0, /* 'f' option set */
98 soption
= 0, /* 's' option used. */
99 files
= 0, /* Number of input files */
100 kludge
= 0, /* Kludge to allow reread of 1st line */
101 okludge
= 0, /* Kludge to indicate reading "o" option */
102 lock
= 0; /* Lock to prevent file indirection */
104 static char pachar
= ' ', /* Prepend/append character */
105 work
[3*NCOLS
+1], /* Work area */
106 *pfirst
, /* Pointer to beginning of line */
107 *plast
, /* Pointer to end of line */
108 *wfirst
= &work
[0], /* Pointer to beginning of work area */
109 *wlast
= &work
[3*NCOLS
], /* Pointer to end of work area */
110 siline
[NCOLS
], /* First standard input line */
111 savchr
[8], /* Holds char stripped from line start */
112 format
[80] = "-8"; /* Array to hold format line */
117 } optl
[MAXOPTS
], /* List of command line options */
118 *flp
= optl
; /* Pointer to next open slot */
120 static void append(int);
121 static void begtrunc(int);
122 static void center(void);
123 static int cnvtspec(char *);
124 static void endtrunc(int);
125 static int inputn(char *);
126 static void inputtabs(int);
127 static void options(int, char **);
128 static void outputtabs(int);
129 static void prepend(int);
130 static void process(FILE *);
131 static char *readline(FILE *, char *);
132 static int readspec(char *);
133 static void sadd(void);
134 static void sstrip(void);
135 static char type(char);
138 main(int argc
, char **argv
)
140 char *scan
; /* String scan pointer */
141 FILE *fp
; /* Pointer to current file */
144 if (optionf
) { /* Write tab spec format line. */
145 (void) fputs("<:t", stdout
);
146 (void) fputs(format
, stdout
);
147 (void) fputs(" d:>\n", stdout
);
153 if ((fp
= fopen(scan
, "r")) == NULL
) {
154 (void) fprintf(stderr
,
155 "newform: can't open %s\n", scan
);
170 options(int argc
, char **argv
) /* Process command line options */
172 int n
; /* Temporary number holder */
173 char *scan
; /* Pointer to individual option strings */
174 char c
; /* Option character */
176 /* changes to option parsing includes checks for exceeding */
177 /* initial buffer sizes */
181 if (*scan
++ == '-') {
182 switch (c
= *scan
++) {
185 flp
->param
= inputn(scan
);
186 if (flp
->param
<= NCOLS
)
189 (void) fprintf(stderr
, "newform: "
190 "prefix request larger than "
191 "buffer, %d\n", NCOLS
);
198 flp
->param
= inputn(scan
);
203 flp
->param
= inputn(scan
);
204 if (flp
->param
<= NCOLS
)
207 (void) fprintf(stderr
, "newform: "
208 "prefix request larger than "
209 "buffer, %d\n", NCOLS
);
215 flp
->param
= *scan
? *scan
: ' ';
225 flp
->param
= cnvtspec(scan
);
229 if (*scan
== '-' && *(scan
+1) == '0' &&
232 /* Above allows the -o-0 option to be ignored. */
234 (void) strcpy(format
, scan
);
236 flp
->param
= cnvtspec(scan
);
239 (void) strcpy(format
, "-8");
244 flp
->param
= ((n
= inputn(scan
)) ? n
: 72);
245 if (flp
->param
<= (3*NCOLS
))
248 (void) fprintf(stderr
, "newform: "
249 "line length request larger "
250 "than buffer, %d \n", (3*NCOLS
));
268 (void) fprintf(stderr
, "usage: newform [-s] [-itabspec] [-otabspec] ");
269 (void) fprintf(stderr
, "[-pn] [-en] [-an] [-f] [-cchar]\n\t\t");
270 (void) fprintf(stderr
, "[-ln] [-bn] [file ...]\n");
273 /* _________________________________________________________________ */
276 inputn(char *scan
) /* Read a command option number */
277 /* Pointer to string of digits */
280 char c
; /* Character being scanned */
283 while ((c
= *scan
++) >= '0' && c
<= '9')
284 n
= n
* 10 + c
- '0';
287 /* _________________________________________________________________ */
290 center(void) /* Center the text in the work area. */
292 char *tfirst
; /* Pointer for moving buffer down */
293 char *tlast
; /* Pointer for moving buffer up */
294 char *tptr
; /* Temporary */
296 if (plast
- pfirst
> MAXLINE
) {
297 (void) fprintf(stderr
, "newform: internal line too long\n");
300 if (pfirst
< &work
[NCOLS
]) {
301 tlast
= plast
+ (&work
[NCOLS
] - pfirst
);
303 while (plast
>= pfirst
) *tlast
-- = *plast
--;
307 tfirst
= &work
[NCOLS
];
309 while (pfirst
<= plast
) *tfirst
++ = *pfirst
++;
316 cnvtspec(char *p
) /* Convert tab specification to tab positions. */
317 /* Pointer to spec string. */
319 int state
, /* DFA state */
320 spectype
, /* Specification type */
321 number
[40], /* Array of read-in numbers */
322 tp
, /* Pointer to last number */
324 int tspec
= 0; /* Tab spec pointer */
325 char c
, /* Temporary */
326 *filep
; /* Pointer to file name */
327 FILE *fp
; /* File pointer */
342 number
[tp
] = c
- '0';
359 number
[tp
] = number
[tp
] * 10 + c
- '0';
369 if (type(c
) == NUMBER
) {
371 number
[++tp
] = c
- '0';
500 if (type(c
) == NUMBER
) {
502 number
[0] = number
[0] * 10 + c
- '0';
503 } else if (c
== '\0') {
513 if (spectype
== 10) {
514 spectype
= nextspec
++;
515 spectbl
[spectype
] = nexttab
;
517 if (number
[0] == 0) number
[0] = 1; /* Prevent infinite loop. */
518 while (*nexttab
< LINELEN
) {
519 *(nexttab
+ 1) = *nexttab
;
520 *++nexttab
+= number
[0];
525 if (spectype
== 11) {
526 spectype
= nextspec
++;
527 spectbl
[spectype
] = nexttab
;
529 for (ix
= 0; ix
<= tp
; ix
++) {
530 *nexttab
++ = number
[ix
];
531 if ((number
[ix
] >= number
[ix
+1]) && (ix
!= tp
))
538 (void) fprintf(stderr
,
539 "newform: tabspec indirection illegal\n");
543 if (spectype
== 12) {
544 if (sitabspec
>= 0) {
547 if (readline(stdin
, siline
) != NULL
) {
549 tspec
= readspec(siline
);
554 if (spectype
== 13) {
555 if ((fp
= fopen(filep
, "r")) == NULL
) {
556 (void) fprintf(stderr
,
557 "newform: can't open %s\n", filep
);
560 (void) readline(fp
, work
);
562 tspec
= readspec(work
);
567 (void) fprintf(stderr
, "newform: tabspec in error\n");
568 (void) fprintf(stderr
,
569 "tabspec is \t-a\t-a2\t-c\t-c2\t-c3\t-f\t-p\t-s\n");
570 (void) fprintf(stderr
,
571 "\t\t-u\t--\t--file\t-number\tnumber,..,number\n");
577 readspec(char *p
) /* Read a tabspec from a file */
578 /* Pointer to buffer to process */
580 int state
, /* Current state */
581 firsttime
, /* Flag to indicate spec found */
582 value
; /* Function value */
583 char c
, /* Char being looked at */
584 *tabspecp
, /* Pointer to spec string */
585 *restore
= " ", /* Character to be restored */
586 repch
; /* Character to replace with */
594 state
= (c
== '<') ? 1 : 0;
597 state
= (c
== ':') ? 2 : 0;
600 state
= (c
== 't') ? 4
601 : ((c
== ' ') || (c
== '\t')) ? 2 : 3;
604 state
= ((c
== ' ') || (c
== '\t')) ? 2 : 3;
612 if ((c
== ' ') || (c
== '\t') || (c
== ':')) {
613 repch
= *(restore
= p
- 1);
616 state
= (c
== ':') ? 6
617 : ((c
== ' ') || (c
== '\t')) ? 5 : 4;
620 state
= (c
== ':') ? 6 : 5;
623 state
= (c
== '>') ? -2 : 5;
626 if (c
== '\n') state
= -1;
629 (void) strcpy(format
, tabspecp
);
630 value
= (state
== -1) ? 0 : cnvtspec(tabspecp
);
636 readline(FILE *fp
, char *area
) /* Read one line from the file. */
637 /* fp - File to read from */
638 /* area - Array of characters to read into */
640 int c
; /* Current character */
641 char *xarea
, /* Temporary pointer to character array */
642 *temp
; /* Array pointer */
646 /* check for existence of stdin before attempting to read */
647 /* kludge refers to reading from stdin to get tabspecs for option -i-- */
650 if (kludge
&& (fp
== stdin
)) {
653 while ((*area
++ = *temp
++) != '\n')
661 /* check for exceeding size of buffer when reading valid input */
663 while (wlast
- area
) {
664 switch (c
= getc(fp
)) {
669 case '\n': /* EOF falls through to here */
676 (void) printf("newform: input line larger than buffer area \n");
681 /* _________________________________________________________________ */
684 type(char c
) /* Determine type of a character */
685 /* Character to check */
687 return ((c
>= '0') && (c
<= '9') ? NUMBER
: c
);
691 process(FILE *fp
) /* Process one line of input */
692 /* File pointer for current input */
694 struct f
*lp
; /* Pointer to structs */
695 char chrnow
; /* For int to char conversion. */
697 while (readline(fp
, &work
[NCOLS
]) != NULL
) {
700 pfirst
= plast
= &work
[NCOLS
];
701 while (*plast
!= '\n') plast
++;
703 /* changes to line parsing includes checks for exceeding */
704 /* line size when modifying text */
706 for (lp
= optl
; lp
< flp
; lp
++) {
707 switch (lp
->option
) {
712 if (lp
->param
<= (plast
- pfirst
))
715 (void) fprintf(stderr
,
717 "request larger than line, %d \n",
722 pachar
= chrnow
? chrnow
: ' ';
725 if (lp
->param
<= (plast
- pfirst
))
728 (void) fprintf(stderr
,
730 "request larger than line, %d \n",
737 inputtabs(lp
->param
);
739 case 'l': /* New eff line length */
740 effll
= lp
->param
? lp
->param
: 72;
746 outputtabs(lp
->param
);
755 (void) fputs(pfirst
, stdout
);
760 append(int n
) /* Append characters to end of line. */
761 /* Number of characters to append. */
763 if (plast
- pfirst
< effll
) {
764 n
= n
? n
: effll
- (plast
- pfirst
);
765 if (plast
+ n
> wlast
) center();
766 while (n
--) *plast
++ = pachar
;
770 /* _________________________________________________________________ */
773 prepend(int n
) /* Prepend characters to line. */
774 /* Number of characters to prepend. */
776 if (plast
- pfirst
< effll
) {
777 n
= n
? n
: effll
- (plast
- pfirst
);
778 if (pfirst
- n
< wfirst
) center();
779 while (n
--) *--pfirst
= pachar
;
782 /* _________________________________________________________________ */
785 begtrunc(int n
) /* Truncate characters from beginning of line. */
786 /* Number of characters to truncate. */
788 if (plast
- pfirst
> effll
) {
789 n
= n
? n
: plast
- pfirst
- effll
;
792 *(pfirst
= plast
= &work
[NCOLS
]) = '\n';
795 /* _________________________________________________________________ */
798 endtrunc(int n
) /* Truncate characters from end of line. */
799 /* Number of characters to truncate. */
801 if (plast
- pfirst
> effll
) {
802 n
= n
? n
: plast
- pfirst
- effll
;
805 *(pfirst
= plast
= &work
[NCOLS
]) = '\n';
812 inputtabs(int p
) /* Expand according to input tab specifications. */
813 /* Pointer to tab specification. */
815 int *tabs
; /* Pointer to tabs */
816 char *tfirst
, /* Pointer to new buffer start */
817 *tlast
; /* Pointer to new buffer end */
818 char c
; /* Character being scanned */
819 int logcol
; /* Logical column */
822 tfirst
= tlast
= work
;
825 while (pfirst
<= plast
) {
826 if (logcol
>= *tabs
) tabs
++;
827 switch (c
= *pfirst
++) {
829 if (logcol
> 1) logcol
--;
831 if (logcol
< *tabs
) tabs
--;
834 while (logcol
< *tabs
) {
850 * Add SCCS SID (generated by a "get -m" command) to the end of each line.
851 * Sequence is as follows for EACH line:
852 * Check for at least 1 tab. Err if none.
853 * Strip off all char up to & including first tab.
854 * If more than 8 char were stripped, the 8 th is replaced by
855 * a '*' & the remainder are discarded.
856 * Unless user specified an "a", append blanks to fill
857 * out line to eff. line length (default= 72 char).
858 * Truncate lines > eff. line length (default=72).
859 * Add stripped char to end of line.
869 while (*c
!= '\t' && *c
!= '\n') {
874 (void) fprintf(stderr
, "not -s format\r\n");
880 savek
= (k
> 7) ? 7 : k
;
881 for (i
= 0; i
<= savek
; i
++) savchr
[i
] = *c
++; /* Tab not saved */
882 if (k
> 7) savchr
[7] = '*';
884 pfirst
= ++savec
; /* Point pfirst to char after tab */
886 /* ================================================================= */
893 for (i
= 0; i
<= savek
; i
++) *plast
++ = savchr
[i
];
898 outputtabs(int p
) /* Contract according to output tab specifications. */
899 /* Pointer to tab specification. */
901 int *tabs
; /* Pointer to tabs */
902 char *tfirst
, /* Pointer to new buffer start */
903 *tlast
, /* Pointer to new buffer end */
904 *mark
; /* Marker pointer */
905 char c
; /* Character being scanned */
906 int logcol
; /* Logical column */
909 tfirst
= tlast
= pfirst
;
911 while (pfirst
<= plast
) {
912 if (logcol
== *tabs
) tabs
++;
913 switch (c
= *pfirst
++) {
915 if (logcol
> 1) logcol
--;
917 if (logcol
< *tabs
) tabs
--;
924 if (logcol
== *tabs
) {
929 } while (*pfirst
++ == ' ');