#include #include #include #include #include #include #include #include double atime() { struct timespec now; clock_gettime(CLOCK_REALTIME, &now); return now.tv_sec + now.tv_nsec * 1e-9; } int main() { int cs = 500; /* allocated number of characters */ char *cb = malloc(cs * sizeof(char)); /* character buffer */ if (cb == NULL) err(1, "malloc"); double *ct = malloc(cs * sizeof(double)); /* character times */ if (ct == NULL) err(1, "malloc"); /* enter "raw" mode */ struct termios orig, raw; int ttyfd = open("/dev/tty", O_RDWR); if (ttyfd == -1) err(1, "open"); tcgetattr(ttyfd, &orig); raw = orig; raw.c_lflag &= ~(ECHO | ICANON); tcsetattr(ttyfd, TCSANOW, &raw); int c; int ci = 0; /* character index */ while (read(ttyfd, &c, 1)) { if (c == 127 && ci > 0) { /* backspace */ ci--; write(ttyfd, &c, 1); continue; } else if (iscntrl(c) && c != '\n') continue; write(ttyfd, &c, 1); cb[ci] = c; ct[ci] = atime(); ci++; if (c == '\n') break; } double finish = atime(); /* finish time */ double tt = 0; /* total time */ double t1 = -1; /* start time of current word */ int words = 0; /* number of words */ int nonspace = 0; /* number of non-space characters */ int i; for (i = 0; i <= ci; i++) { if (cb[i] == ' ' || cb[i] == '\n') { if (t1 == -1) continue; tt += ct[i - 1] - t1; t1 = -1; if (cb[i] == '\n') break; else continue; } if (t1 == -1) { t1 = ct[i]; words++; } nonspace++; } /* print statistics */ printf("%d\twords\n", words); printf("%d\tcharacters\n", ci - 1); printf("%d\tcharacters inside words\n", nonspace); printf("%.4f\tseconds\n", finish - ct[0]); printf("%.4f\tseconds inside words\n", tt); printf("%.4f\tseconds per character\n", tt / (ci - 1)); printf("%.4f\tseconds per character inside word\n", tt / nonspace); printf("%.4f\tseconds per word\n", tt / words); /* restore original terminal settings */ tcsetattr(ttyfd, TCSANOW, &orig); }