/* File : ll.c Author : Richard A. O'Keefe Updated: %G% Purpose: Print the longest line in each file. Usage : ll file... TODO : handle UTF-8. If there are no file names in the command line, the file name "-" is used. As a file name, "-" means to use standard input, and should be used at most once, but this is not checked. For each file, - if the file cannot be read, an error message is printed and processing stops. - if an error occurs while processing a file, an error message is printed and processing stops. - otherwise one line is printed to standard input. * If the file is empty, the line is :empty * If the longest line exceeds 1024 characters, the line is :: > 1024 * If the longest line has no more than 1024 characters, it's ::: where is the 1-origin index of the first line to have the greatest number of columns. TABs are expanded according to the 40-year UNIX convention of tab stops being set every 8 columns. CR characters are ignored. Currently this is set up for 8-bit character sets. All bytes other than TAB, CR, and LF are taken as representing one-column characters. To handle UTF-8, we would need to + distinguish between buflen (in bytes) and bufcnt (in chars). + don't count bytes 10xxxxxx towards bufcnt + do this only in a UTF-8 locale. */ #include #include #include #define MAX_LINE_LENGTH 1024 static char buffer[MAX_LINE_LENGTH+1] = ""; static int buflen = 0; static int overflow = 0; static int read_line(char const *file_name, FILE *in) { int i; /* index into buffer */ int c; /* unsigned character U {EOF} */ i = 0; for (;;) { c = getc_unlocked(in); if (c == '\n' || c < 0) break; if (c == '\r') continue; if (i != MAX_LINE_LENGTH) { if (c == '\t') { do buffer[i++] = ' '; while (i % 8 != 0); } else { buffer[i++] = (char)c; } } else { overflow = 1; } } if (c < 0) { if (ferror(in)) perror(file_name), exit(EXIT_FAILURE); if (i == 0) return 0; } buflen = i; buffer[i] = '\0'; return 1; } static void process(char const *file_name) { char max_str[MAX_LINE_LENGTH + 1]; int max_len = -1; int max_num = 0; int line_no; FILE *in = 0 == strcmp("-", file_name) ? stdin : fopen(file_name, "r"); if (in == 0) perror(file_name), exit(EXIT_FAILURE); overflow = 0; for (line_no = 1; read_line(file_name, in); line_no++) { if (buflen > max_len) { (void)strcpy(max_str, buffer); max_len = buflen; max_num = line_no; } } (void)fclose(in); printf("%s:%d:\t", file_name, max_num); printf(overflow ? " >%5d " : "%7d ", max_len); printf("%s\n", max_str); } int main(int argc, char **argv) { int i; if (argc < 2) { process("-"); } else { for (i = 1; i < argc; i++) process(argv[i]); } return 0; }