|
|
1.1 root 1: #include <stdio.h>
2: #include <ctype.h>
3: #include "mail.h"
4: #include "string.h"
5:
6: /* imports */
7: extern char *malloc();
8: extern char *realloc();
9: extern void exit();
10:
11: /* global to this file */
12: #define STRLEN 128
13: #define STRALLOC 128
14: #define MAXINCR 250000
15:
16: /* buffer pool for allocating string structures */
17: typedef struct {
18: string s[STRALLOC];
19: int o;
20: } stralloc;
21: static stralloc *freep=NULL;
22:
23: /* pool of freed strings */
24: static string *freed=NULL;
25:
26: void
27: s_free(sp)
28: string *sp;
29: {
30: if (sp != NULL) {
31: sp->ptr = (char *)freed;
32: freed = sp;
33: }
34: }
35:
36: /* allocate a string head */
37: static string *
38: s_alloc() {
39: if (freep==NULL || freep->o >= STRALLOC) {
40: freep = (stralloc *)malloc(sizeof(stralloc));
41: if (freep==NULL) {
42: perror("allocating string");
43: exit(1);
44: }
45: freep->o = 0;
46: }
47: return &(freep->s[freep->o++]);
48: }
49:
50: /* create a new `short' string */
51: extern string *
52: s_new()
53: {
54: string *sp;
55:
56: if (freed!=NULL) {
57: sp = freed;
58: freed = (string *)(freed->ptr);
59: sp->ptr = sp->base;
60: return sp;
61: }
62: sp = s_alloc();
63: sp->base = sp->ptr = malloc(STRLEN);
64: if (sp->base == NULL) {
65: perror("allocating string");
66: exit(1);
67: }
68: sp->end = sp->base + STRLEN;
69: s_terminate(sp);
70: return sp;
71: }
72:
73: /* grow a string's allocation by at least `incr' bytes */
74: extern int
75: s_simplegrow(sp, incr)
76: string *sp;
77: int incr;
78: {
79: char *cp;
80: int size;
81:
82: /*
83: * take a larger increment to avoid mallocing too often
84: */
85: if((sp->end-sp->base) < incr && MAXINCR < incr)
86: size = (sp->end-sp->base) + incr;
87: else if((sp->end-sp->base) > MAXINCR)
88: size = (sp->end-sp->base)+MAXINCR;
89: else
90: size = 2*(sp->end-sp->base);
91:
92: cp = realloc(sp->base, size);
93: if (cp == NULL) {
94: perror("string:");
95: exit(1);
96: }
97: sp->ptr = (sp->ptr - sp->base) + cp;
98: sp->end = cp + size;
99: sp->base = cp;
100: }
101:
102: /* grow a string's allocation */
103: extern int
104: s_grow(sp, c)
105: string *sp;
106: int c;
107: {
108: s_simplegrow(sp, 2);
109: s_putc(sp, c);
110: return c;
111: }
112:
113: /* return a string containing a character array (this had better not grow) */
114: string *
115: s_array(cp, len)
116: char *cp;
117: int len;
118: {
119: string *sp = s_alloc();
120:
121: sp->base = sp->ptr = cp;
122: sp->end = sp->base + len;
123: return sp;
124: }
125:
126: /* return a string containing a copy of the passed char array */
127: extern string*
128: s_copy(cp)
129: char *cp;
130: {
131: string *sp;
132: int len;
133:
134: sp = s_alloc();
135: len = strlen(cp)+1;
136: sp->base = malloc(len);
137: if (sp->base == NULL) {
138: perror("string:");
139: exit(1);
140: }
141: sp->end = sp->base + len; /* point past end of allocation */
142: strcpy(sp->base, cp);
143: sp->ptr = sp->end - 1; /* point to NULL terminator */
144: return sp;
145: }
146:
147: /* convert string to lower case */
148: extern int
149: s_tolower(sp)
150: string *sp;
151: {
152: char *cp;
153:
154: for(cp=sp->ptr; *cp; cp++)
155: if(isupper(*cp))
156: *cp = tolower(*cp);
157: }
158:
159: /* append a char array to a string */
160: extern string *
161: s_append(to, from)
162: register string *to;
163: register char *from;
164: {
165: int want, have;
166:
167: if (to == NULL)
168: to = s_new();
169: if (from == NULL)
170: return to;
171: for(; *from; from++)
172: s_putc(to, *from);
173: s_terminate(to);
174: return to;
175: }
176:
177: /* append a char array ( of up to n characters) to a string */
178: extern string *
179: s_nappend(to, from, n)
180: register string *to;
181: register char *from;
182: {
183: int want, have;
184:
185: if (to == NULL)
186: to = s_new();
187: if (from == NULL)
188: return to;
189: for(; *from && n; from++, n--)
190: s_putc(to, *from);
191: s_terminate(to);
192: return to;
193: }
194:
195: /* Append a logical input sequence into a string. Ignore blank and
196: * comment lines. Backslash preceding newline indicates continuation.
197: * The `lineortoken' variable indicates whether the sequence to beinput
198: * is a whitespace delimited token or a whole line.
199: *
200: * Returns a pointer to the string (or NULL). Trailing newline is stripped off.
201: */
202: extern string *
203: s_seq_read(fp, to, lineortoken)
204: FILE *fp; /* stream to read from */
205: string *to; /* where to put token */
206: int lineortoken; /* how the sequence terminates */
207: {
208: register int c;
209: int done=0;
210:
211: if(feof(fp))
212: return NULL;
213:
214: /* get rid of leading goo */
215: do {
216: c = getc(fp);
217: switch(c) {
218: case EOF:
219: if (to != NULL)
220: s_terminate(to);
221: return NULL;
222: case '#':
223: while((c = getc(fp)) != '\n' && c != EOF);
224: break;
225: case ' ':
226: case '\t':
227: case '\n':
228: case '\r':
229: case '\f':
230: break;
231: default:
232: done = 1;
233: break;
234: }
235: } while (!done);
236:
237: if (to == NULL)
238: to = s_new();
239:
240: /* gather up a sequence */
241: for (;;) {
242: switch(c) {
243: case '\\':
244: c = getc(fp);
245: if (c != '\n') {
246: s_putc(to, '\\');
247: s_putc(to, c);
248: }
249: break;
250: case EOF:
251: case '\r':
252: case '\f':
253: case '\n':
254: s_terminate(to);
255: return to;
256: case ' ':
257: case '\t':
258: if (lineortoken == TOKEN) {
259: s_terminate(to);
260: return to;
261: }
262: /* fall through */
263: default:
264: s_putc(to, c);
265: break;
266: }
267: c = getc(fp);
268: }
269: }
270:
271: /* Append an input line to a string.
272: *
273: * Returns a pointer to the string (or NULL).
274: * Trailing newline is left on.
275: */
276: extern char *
277: s_read_line(fp, to)
278: register FILE *fp;
279: register string *to;
280: {
281: register int c;
282: register int len=0;
283:
284: s_terminate(to);
285:
286: /* end of input */
287: if (feof(fp) || (c=getc(fp)) == EOF)
288: return NULL;
289:
290: /* gather up a line */
291: for(;;) {
292: len++;
293: switch(c) {
294: case EOF:
295: s_terminate(to);
296: return to->ptr-len;
297: case '\n':
298: s_putc(to, '\n');
299: s_terminate(to);
300: return to->ptr-len;
301: default:
302: s_putc(to, c);
303: break;
304: }
305: c=getc(fp);
306: }
307: }
308:
309: /*
310: * Read till eof or some limit is passed. If the limit is passed,
311: * return a negative counr.
312: */
313: extern int
314: s_read_to_lim(fp, to, lim)
315: register FILE *fp;
316: register string *to;
317: int lim;
318: {
319: register int c;
320: register int got;
321: register int have;
322:
323: s_terminate(to);
324:
325: for(;;){
326: if(lim && to->ptr - to->base > lim){
327: s_terminate(to);
328: return -(to->ptr - to->base);
329: }
330: if(feof(fp))
331: break;
332: /* allocate room for a full buffer */
333: have = to->end - to->ptr;
334: if(have<4096)
335: s_simplegrow(to, 4096);
336:
337: /* get a buffers worth */
338: have = to->end - to->ptr;
339: got = fread(to->ptr, 1, have, fp);
340: if(got<=0)
341: break;
342: to->ptr += got;
343: }
344:
345: /* null terminate the line */
346: s_terminate(to);
347: return to->ptr - to->base;
348: }
349:
350: /*
351: * read to eof
352: */
353: extern int
354: s_read_to_eof(fp, to)
355: register FILE *fp;
356: register string *to;
357: {
358: return s_read_to_lim(fp, to, 0);
359: }
360:
361: /* Get the next field from a string. The field is delimited by white space,
362: * single or double quotes.
363: */
364: extern string *
365: s_parse(from, to)
366: string *from; /* string to parse */
367: string *to; /* where to put parsed token */
368: {
369: while (isspace(*from->ptr))
370: from->ptr++;
371: if (*from->ptr == '\0')
372: return NULL;
373: if (to == NULL)
374: to = s_new();
375: if (*from->ptr == '\'') {
376: from->ptr++;
377: for (;*from->ptr != '\'' && *from->ptr != '\0'; from->ptr++)
378: s_putc(to, *from->ptr);
379: if (*from->ptr == '\'')
380: from->ptr++;
381: } else if (*from->ptr == '"') {
382: from->ptr++;
383: for (;*from->ptr != '"' && *from->ptr != '\0'; from->ptr++)
384: s_putc(to, *from->ptr);
385: if (*from->ptr == '"')
386: from->ptr++;
387: } else {
388: for (;!isspace(*from->ptr) && *from->ptr != '\0'; from->ptr++)
389: s_putc(to, *from->ptr);
390: }
391: s_terminate(to);
392:
393: return to;
394: }
395:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.