#include #include #include char *progname; int charmode = 0; int linemode = 0; char *word = NULL; int xflag = 0; struct node { struct node *next; char *val; }; void usage(void) { fprintf(stderr, "Usage: %s [-c] [-l] [-s WORD [-x]] [FILE...]\n", progname); exit(1); } /* ** returns line in new memory */ char * readlongline(FILE *fp) { char *bufp; int size = 8; char *cp; int offset = 0; if (!(bufp = malloc(size))) { fprintf(stderr, "Out of mem\n"); exit(1); } *bufp = '\0'; cp = bufp; while (fgets(cp, size-offset, fp)) { cp += strlen(cp) - 1; if (*cp == '\n') { *cp = '\0'; return bufp; } size *= 2; if (!(bufp = realloc(bufp, size))) { fprintf(stderr, "Out of mem\n"); exit(1); } offset = strlen(bufp); cp = bufp + offset; } return (*bufp) ? bufp : NULL; /* possibly incomplete last line */ } void rev_line(char *line) { char *cp = line; char *ep = line + strlen(line) - 1; char tmp; while (cp < ep) { tmp = *cp; *cp = *ep; *ep = tmp; cp++; ep--; } } void processfile(FILE *fp) { char *line; struct node *stack = NULL; struct node *np; int revline; int hasword = word ? 0 : 1; while ((line = readlongline(fp))) { revline = word ? 0 : 1; if (word && strstr(line, word)) { hasword = 1; revline = 1; } if (charmode && (xflag != revline)) { rev_line(line); } if (linemode) { if (!(np = malloc(sizeof(struct node)))) { fprintf(stderr, "Out of mem"); exit(1); } np->val = line; /* push */ np->next = stack; stack = np; } else { printf("%s\n", line); free(line); } } if (linemode) { if (hasword == xflag) { struct node *temp = NULL; /* reverse order of stack, i.e. restore normal order */ while ((np = stack)) { stack = np->next; np->next = temp; temp = np; } stack = temp; } while ((np = stack)) { stack = stack->next; /* pop */ printf("%s\n", np->val); free(np->val); free(np); } } } int main(int argc, char *argv[]) { char *cp; FILE *fp; progname = argv[0]; argc--; argv++; /* remove program name */ if (strcmp(progname, "lreverse")==0 || strcmp(progname, "./lreverse")==0) { linemode = 1; } for (; *argv && **argv=='-'; argc--,argv++) { cp = *argv + 1; if (!*cp) { /* ``-'' is no option but use stdin as first file */ break; } switch (*cp) { case 'c': charmode = 1; break; case 'l': linemode = 1; break; case 'x': if (cp[1]) { fprintf(stderr, "Unknown option `-%s'\n", cp); usage(); } xflag = 1; break; case 's': if (cp[1]) { word = cp + 1; } else if (*++argv) { word = *argv; argc--; } else { usage(); } break; default: usage(); } } if (!linemode && !charmode) { charmode = 1; } if (!*argv) { processfile(stdin); return 0; } for (; *argv; argv++,argc--) { if (strcmp(*argv, "-") == 0) { processfile(stdin); } else { if (!(fp = fopen(*argv, "r"))) { fprintf(stderr,"Could not open `%s'\n", *argv); continue; } processfile(fp); fclose(fp); } } return 0; }