]> diplodocus.org Git - nmh/blob - docs/historical/mh-jun-1982/Extras/libh/inputf.c
Updated documentation and comments about sendmail/pipe.
[nmh] / docs / historical / mh-jun-1982 / Extras / libh / inputf.c
1 #ifdef COMMENT
2 Proprietary Rand Corporation, 1981.
3 Further distribution of this software
4 subject to the terms of the Rand
5 license agreement.
6 #endif
7
8 #
9 /* inputf is roughly complementary to printf,
10 except input comes from getchar (may be
11 user supplied, must return 0 at eof). in addition
12 all args must be pointers (addresses). the first arg
13 is the format string. '%' is used as the escape char as in
14 printf. the general format is %w.dc where w and d are decimal
15 character counts, and c is one of (d, o, i, f, e, s, c, x).
16 the args are all assumed to be pointers to the appropriate
17 typed args -- note all floating point is assumed to be float
18 unless the %e format is used (extended float). if w is omitted
19 the field ends with the first field delimeter (typically, space, comma,
20 and newline -- these can be specified by following the specification
21 by a list of chars before the next '%'). d represents the default
22 number of decimal places for 'f' and 'e' if no explicit
23 decimal point. for 's' w is the width of the field, and d is
24 the maximum number of chars after stripping off delimeters
25 on either end. s and c are approximately identical, except
26 that s returns a pointer into a static buffer, and c returns char
27 by char into the program itself, which means a 'd' specification
28 for c is essential, and in fact 1 is assumed as a default (as opposed
29 to infinity for s). if a w field is specified, the input data
30 is assumed to be in a fixed format, with exactly w columns
31 devoted to the designated field. this means that data in this format
32 does not have to be separated by blanks, etc. chars in the format
33 string before the first '%' are output before any requests
34 to the subroutine for chars. e.g.:
35 inputf("-> %i%e%s\n",&integ, &dbl, &charptr);
36 would read an integer into integ, a double into dbl, and a string
37 terminated only by a <nl> into a static buffer, returning its start
38 addr in charptr, after prompting with "-> ". */
39 #define DFTSEP ",; \t\n\r" /* default field separators */
40 #define NEXTCHR getchar() /* character input routine */
41 #define SCBLEN 100 /* max. no. of chars in static char buff */
42 struct { float *fltp; };
43 struct { double *dblp; };
44 inputf(format,arg1,arg2,arg3)
45 char *format;
46 {
47 register char *fp, *cp, cc;
48 int **ap;
49 int fld, val, wv, dv, radix;
50 char formc, negflg, negexp, *fsp, *scp;
51 static char scbuf[SCBLEN], fldsep[10];
52 double dval;
53
54 ap = &arg1;
55 fp = format;
56 scp = scbuf; /* init static string pointer */
57
58 while ((cc = *fp++) && cc != '%') putchar(cc);
59 flush();
60
61 fld = 0; /* used as return value when error found */
62 while (cc) {
63 fld--;
64 wv = 0; dv = 0; /* init w.d fields */
65 while (numeric(cc = *fp++)) wv = wv*10 + cc - '0';
66 if (cc == '.')
67 while (numeric(cc = *fp++)) dv = dv*10 + cc - '0';
68 if (!wv) wv--; if (!dv) dv--; /* zero --> minus one */
69 formc = cc; /* save format character */
70 fsp = cp = fldsep; /* collect terminators */
71 while (*cp++ = *fp)
72 if (*fp++ == '%') {
73 fp--;
74 *--cp = 0;
75 break;
76 }
77 if (!*fsp) fsp = DFTSEP;
78 switch (formc) {
79 case 'o':
80 radix = 8;
81 goto ido;
82 case 'd':
83 case 'i':
84 radix = 10;
85 ido:
86 val = 0;
87 negflg = 0;
88 while ((cc = NEXTCHR) && (cc == ' ' || cc == '-') && --wv)
89 if (cc == '-') negflg++;
90 if (!cc) return (fld); /* return error if eof found */
91 if (formc == 'i' && cc == '0') radix = 8;
92 if (wv) do {
93 if (numeric (cc)) {
94 val = val*radix + cc - '0';
95 } else if (any(cc,fsp))
96 break;
97 } while (--wv && (cc = NEXTCHR));
98 if (negflg) val = -val;
99 **ap++ = val;
100 break;
101 case 'c':
102 if (dv < 0)
103 if (wv < 0) dv = 1;
104 else dv = wv;
105 cp = *ap++;
106 goto casecs;
107 case 's':
108 cp = scp;
109 val = scbuf + SCBLEN - 1 - cp; /* calc max. limit on input */
110 if (dv<0 || dv>val)
111 if ((dv = val) <= 0) return (fld);
112 casecs:
113 while ((cc = NEXTCHR) && cc == ' ' && --wv);
114 if (!cc) return (fld); /* return error if eof found */
115 if (wv) do {
116 if (any(cc,fsp)) break;
117 if (!dv--) return (fld); /* too big */
118 *cp++ = cc;
119 } while (--wv && (cc = NEXTCHR));
120 if (dv || formc == 's') *cp++ = 0;
121 if (formc == 'c') break;
122 **ap++ = scp;
123 scp = cp;
124 break;
125 case 'x':
126 while ((cc = NEXTCHR) && cc == ' ' && --wv);
127 if (wv)
128 while (!any(cc,fsp) && --wv && (cc = NEXTCHR));
129 break;
130 case 'f':
131 case 'e':
132 dval = 0.;
133 negflg = 0;
134 val = 0; /* used for explicit exponent */
135 radix = 0100000; /* used for decimal place count */
136 while ((cc = NEXTCHR) && (cc == ' ' || cc == '-') && --wv)
137 if (cc == '-') negflg++;
138 if (!cc) return (fld); /* return error if eof found */
139 if (wv) do {
140 if (numeric(cc)) {
141 dval = dval*10. + (cc-'0');
142 radix++;
143 } else if (cc == '.') {
144 radix = 0;
145 dv = -1;
146 } else if (any(cc,fsp)) break;
147 else if (cc == 'e') {
148 negexp = 0;
149 while ((cc = NEXTCHR) && !numeric(cc) && --wv)
150 if (cc == '-') negexp++;
151 if (!cc) return (fld); /* return error if eof found */
152 if (wv) do {
153 if (numeric(cc))
154 val = val*10 + cc-'0';
155 else if (any(cc,fsp)) break;
156 } while (--wv && (cc = NEXTCHR));
157 if (negexp) val = -val;
158 break;
159 }
160 } while (--wv && (cc = NEXTCHR));
161 if (dv > 0) radix = dv;
162 if (radix > 0) val =- radix;
163 if (val >= 0)
164 while (--val >= 0) dval = dval*10.;
165 else
166 while (++val <= 0) dval = dval/10.;
167 if (negflg) dval = -dval;
168 if (formc == 'f')
169 *ap->fltp = dval;
170 else
171 *ap->dblp = dval;
172 ap++;
173 break;
174 default:
175 write(2,"bad format specification",20);
176 exit(fld);
177 }
178 cc = *fp++;
179 }
180 return (0);
181 }
182 numeric(chr)
183 {
184 return (chr >= '0' && chr <=