|
|
1.1 root 1: /*
2: * echo -- print arguments
3: *
4: * Usage: echo [ -n ] [ argument ... ]
5: *
6: * Option: -n Do not print terminal newline
7: *
8: * Note: The following C-like escape conventions are usable with
9: * ECHO; beware of conflicts with the shell's use of \:
10: * \b backspace
11: * \c print line without new-line
12: * (same as -n option)
13: * \f form-feed
14: * \n new-line
15: * \r carriage returnm
16: * \t tab
17: * \v vertical tab
18: * \\ backslash
19: * \0x where x represents the octal value of an
20: * ASCII character
21: *
22: */
23:
24: static char buf[512]; /* working buffer */
25: static char * bufend = &buf[sizeof buf]; /* pointer to end ogf buf */
26: static char * bufp = &buf[0]; /* pointer to current offset in buf */
27: static char lastch = '\n'; /* last output char (if non-zero) */
28: static int asc; /* octal value */
29:
30: main( argc, argv )
31: int argc;
32: register char ** argv;
33: {
34: extern echos();
35:
36: if ( strcmp( *++argv, "-n" ) == 0 ) {
37: lastch = 0;
38: ++argv;
39: }
40:
41: /*
42: * Read all argument strings into buffer. Separate each argument
43: * with a blank.
44: */
45: while ( *argv ) {
46: echos( *argv );
47: if ( *++argv )
48: echos( " " );
49: }
50:
51: if ( *bufp = lastch )
52: ++bufp;
53:
54: if ( bufp > buf )
55: write( 1, buf, bufp - buf );
56:
57: exit( 0 );
58: }
59:
60: /*
61: * static
62: * echos( sp )
63: * char * sp;
64: *
65: * Input: sp - pointer to string to append to output buffer.
66: *
67: * Action: Transfer string to output buffer at offset specified by 'bufp'.
68: * If buffer becomes full during transfer, write buffer to stdout,
69: * and wrap 'bufp' back to beginning of buffer.
70: */
71:
72: static
73: echos( sp )
74: register char * sp;
75: {
76: register char * dp = bufp;
77: extern char * getoct();
78:
79: /*
80: * Copy argument to buffer.
81: */
82: for ( ; *sp ; ++sp ) {
83: if ( *sp == '\\' ) {
84: if ( *++sp == '\0' )
85: break;
86:
87: switch (*sp) {
88: case 'b': *dp = '\b'; break;
89: case 'f': *dp = '\f'; break;
90: case 'n': *dp = '\n'; break;
91: case 'r': *dp = '\r'; break;
92: case 't': *dp = '\t'; break;
93: case 'v': *dp = 013; break;
94: case 'c': lastch = 0; --dp; break;
95: case '0': sp = getoct( ++sp );
96: *dp = (char)asc;
97: break;
98: default : *dp = *sp; break;
99: }
100: } else
101: *dp = *sp;
102:
103: /*
104: * Empty buffer to standard output if full.
105: */
106: if ( ++dp == bufend ) {
107: write( 1, buf, sizeof buf );
108: dp = buf;
109: }
110: }
111:
112: bufp = dp;
113: }
114:
115: /*
116: * char *
117: * getoct( s )
118: * char * s;
119: *
120: * Input: s - pointer to current offset in string.
121: *
122: * Action: Read octal value from string ( up to 3 characters ).
123: *
124: * Return: Pointer to current offset in string.
125: */
126: char *
127: getoct( s )
128: char * s;
129: {
130: int i; /* working counter */
131:
132: i = 0;
133: asc = 0; /* clear octal value buffer */
134:
135: while ( (*s) && (*s >= '0') && (*s <= '7') && ( i < 3 ) ) {
136: asc = asc * 8 + *s - '0'; /* octal value accumulation */
137: ++s;
138: ++i;
139: }
140:
141: return( --s );
142: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.