6414c2df28f98b7b5b8ffdf1574a6abbda7d3960
[calc.git] / calc.c
1 /* depend: */
2 /* cflags: */
3 /* linker: atoi.o fdprintf.o */
4
5 //#include <malloc.h>
6 #include <stddef.h>
7 #include <stdio.h>
8 #include <unistd.h>
9
10 #include "atoi.h"
11 #include "fdprintf.h"
12
13 /* constants */
14
15 //#define BUFFER_SIZE 4096
16 #define BUFFER_SIZE 256
17
18 /* macros */
19
20 #define CEIL(x, y) (((x) + (y) - 1) / (y))
21 #define MIN(x, y) (((x) < (y)) ? (x) : (y))
22 #define MAX(x, y) (((x) > (y)) ? (x) : (y))
23
24 /* verbose */
25
26 #define ERROR 0
27 #define WARNING 1
28 #define INFO 2
29 #define DEBUG 3
30
31 #define VERBOSE(level, statement...) do { if (level <= verbose) { statement; } } while(0)
32
33 /* gobal variables */
34
35 char *progname = NULL;
36 int verbose = 2;
37
38 /* help function */
39
40 int usage (int ret)
41 {
42 int fd = ret ? stdfderr : stdfdout;
43 fdprintf (fd, "usage: %s\n", progname);
44 fdprintf (fd, " -h : help message\n");
45 fdprintf (fd, " -v : verbose level (%d)\n", verbose);
46
47 return ret;
48 }
49
50 /* main function */
51
52 int main (int argc, char *argv[])
53 {
54 char buffer[BUFFER_SIZE + 1] = {0};
55 char *pt = buffer;
56 int i = 0, j = 0, n;
57
58 /* program name */
59
60 progname = argv[0];
61 while (progname[i] != '\0') {
62 if ((progname[i] == '/') || (progname[i] == '\\')) {
63 progname += i + 1;
64 i = 0;
65 } else {
66 i++;
67 }
68 }
69
70 /* argument processing */
71
72 while (argc-- > 1) {
73 char *arg = *(++argv);
74 if (arg[0] != '-') {
75 PRINTERR ("%s: invalid option -- %s\n", progname, arg);
76 return usage (1);
77 }
78 char c = arg[1];
79 switch (c) {
80 case 'v':
81 arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
82 if (arg == NULL) {
83 PRINTERR ("%s: missing verbose level\n", progname);
84 return usage (1);
85 }
86 verbose = atoi (arg);
87 break;
88 case 'h':
89 default:
90 return usage (c != 'h');
91 }
92 }
93
94 /* read from input stream */
95
96 while ((n = read (stdfdin, pt, BUFFER_SIZE - (pt - buffer))) != 0) {
97 VERBOSE (DEBUG, PRINTOUT ("read %d bytes\n", n));
98 n += (pt - buffer);
99
100 /* look for end of line */
101 for (i = 0, j = 0; i < n; i++) {
102 if (buffer[i] == '\n') {
103 buffer[i] = 0;
104 VERBOSE (DEBUG, PRINTOUT ("line(%d): %s\n", j, buffer + j));
105 //fsync (stdfdout);
106 fflush (stdout);
107 j = i + 1;
108 }
109 }
110
111 /* keep remainding */
112 if (j < n) {
113 for (i = 0; i < n - j; i++) {
114 buffer[i] = buffer[i + j];
115 }
116 pt = buffer + n - j;
117 for (i = n - j; i < BUFFER_SIZE; i++) {
118 buffer[i] = 0;
119 }
120 }
121 }
122
123 return 0;
124 }
125
126 // test: calc.exe -h
127 // test: calc.exe -h | awk '/usage:/ { rc=1 } END { exit (1-rc) }'
128 // test: calc.exe -_ 2> /dev/null | awk 'END { if (NR == 0) { exit(0) } else exit (1) }'
129 // test: calc.exe -_ 2>&1 | awk '/usage:/ { rc=1 } END { exit (1-rc) }'
130 // test: echo "foo\nbar\nfoobar" | calc.exe -v3
131
132 /* vim: set ts=4 sw=4 et: */