1 /*
2 * Copyright (c) 2003
3 * David Leonard. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of David Leonard nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #if HAVE_CONFIG_H
32 # include <config.h>
33 #endif
34
35 #if STDC_HEADERS
36 # include <stdio.h>
37 #endif
38
39 #include <see/type.h>
40 #include <see/input.h>
41 #include <see/mem.h>
42
43 /*
44 * an n-character lookahead input filter
45 */
46
47 static SEE_unicode_t la_next(struct SEE_input *);
48 static void la_close(struct SEE_input *);
49
50 static struct SEE_inputclass la_inputclass = {
51 la_next,
52 la_close
53 };
54
55 struct lookahead {
56 struct SEE_input input;
57 struct SEE_input * sub;
58 int max, ptr;
59 struct {
60 SEE_unicode_t ch;
61 int eof;
62 } buf[1];
63 };
64
65 static SEE_unicode_t
la_next(inp)66 la_next(inp)
67 struct SEE_input *inp;
68 {
69 struct lookahead *la = (struct lookahead *)inp;
70 SEE_unicode_t next = inp->lookahead;
71 struct SEE_input *sub = la->sub;
72
73 inp->lookahead = la->buf[la->ptr].ch;
74 inp->eof = la->buf[la->ptr].eof;
75 la->buf[la->ptr].ch = sub->lookahead;
76 la->buf[la->ptr].eof = sub->eof;
77 if (!sub->eof)
78 SEE_INPUT_NEXT(sub);
79 la->ptr = (la->ptr + 1) % la->max;
80 return next;
81 }
82
83 /*
84 * Return the lookahead buffer that we have available
85 */
86 int
SEE_input_lookahead_copy(inp,buf,buflen)87 SEE_input_lookahead_copy(inp, buf, buflen)
88 struct SEE_input *inp;
89 SEE_unicode_t *buf;
90 int buflen;
91 {
92 struct lookahead *la = (struct lookahead *)inp;
93 int i;
94
95 if (buflen <= 0 || inp->eof)
96 return 0;
97 buf[0] = inp->lookahead;
98 for (i = 0; i < la->max && i + 1 < buflen &&
99 !la->buf[(la->ptr + i) % la->max].eof; i++)
100 buf[i+1] = la->buf[(la->ptr + i) % la->max].ch;
101 return i + 1;
102 }
103
104 static void
la_close(inp)105 la_close(inp)
106 struct SEE_input *inp;
107 {
108 struct lookahead *la = (struct lookahead *)inp;
109
110 SEE_INPUT_CLOSE(la->sub);
111 }
112
113 struct SEE_input *
SEE_input_lookahead(sub,max)114 SEE_input_lookahead(sub, max)
115 struct SEE_input *sub;
116 int max;
117 {
118 struct lookahead *la;
119 int i;
120
121 la = (struct lookahead *)SEE_malloc(sub->interpreter,
122 sizeof (struct lookahead) + (max - 1) * sizeof la->buf[0]);
123 la->input.inputclass = &la_inputclass;
124 la->input.filename = sub->filename;
125 la->input.first_lineno = sub->first_lineno;
126 la->input.interpreter = sub->interpreter;
127 la->sub = sub;
128 la->ptr = 0;
129 la->max = max;
130 for (i = 0; i < max + 1; i++)
131 la_next((struct SEE_input *)la);
132 return (struct SEE_input *)la;
133 }
134