|
|
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.