glsl: Correctly handle line numbering.
[mesa.git] / src / glsl / pp / sl_pp_version.c
1 /**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include "sl_pp_version.h"
29
30
31 static int
32 _parse_integer(const char *input,
33 unsigned int *number)
34 {
35 unsigned int n = 0;
36
37 while (*input >= '0' && *input <= '9') {
38 if (n * 10 < n) {
39 /* Overflow. */
40 return -1;
41 }
42
43 n = n * 10 + (*input++ - '0');
44 }
45
46 if (*input != '\0') {
47 /* Invalid decimal number. */
48 return -1;
49 }
50
51 *number = n;
52 return 0;
53 }
54
55
56 int
57 sl_pp_version(struct sl_pp_context *context,
58 const struct sl_pp_token_info *input,
59 unsigned int *version,
60 unsigned int *tokens_eaten)
61 {
62 unsigned int i = 0;
63 unsigned int line = context->line;
64
65 /* Default values if `#version' is not present. */
66 *version = 110;
67 *tokens_eaten = 0;
68
69 /* There can be multiple `#version' directives present.
70 * Accept the value of the last one.
71 */
72 for (;;) {
73 int found_hash = 0;
74 int found_version = 0;
75 int found_number = 0;
76 int found_end = 0;
77
78 /* Skip whitespace and newlines and seek for hash. */
79 while (!found_hash) {
80 switch (input[i].token) {
81 case SL_PP_NEWLINE:
82 line++;
83 /* pass thru */
84 case SL_PP_WHITESPACE:
85 i++;
86 break;
87
88 case SL_PP_HASH:
89 i++;
90 found_hash = 1;
91 break;
92
93 default:
94 return 0;
95 }
96 }
97
98 /* Skip whitespace and seek for `version'. */
99 while (!found_version) {
100 switch (input[i].token) {
101 case SL_PP_WHITESPACE:
102 i++;
103 break;
104
105 case SL_PP_IDENTIFIER:
106 {
107 const char *id = sl_pp_context_cstr(context, input[i].data.identifier);
108
109 if (!id) {
110 return -1;
111 }
112 if (strcmp(id, "version")) {
113 return 0;
114 }
115 i++;
116 found_version = 1;
117 }
118 break;
119
120 default:
121 return 0;
122 }
123 }
124
125 /* Skip whitespace and seek for version number. */
126 while (!found_number) {
127 switch (input[i].token) {
128 case SL_PP_WHITESPACE:
129 i++;
130 break;
131
132 case SL_PP_NUMBER:
133 {
134 const char *num = sl_pp_context_cstr(context, input[i].data.number);
135
136 if (!num) {
137 return -1;
138 }
139 if (_parse_integer(num, version)) {
140 /* Expected version number. */
141 return -1;
142 }
143 i++;
144 found_number = 1;
145 }
146 break;
147
148 default:
149 /* Expected version number. */
150 return -1;
151 }
152 }
153
154 /* Skip whitespace and seek for either newline or eof. */
155 while (!found_end) {
156 switch (input[i].token) {
157 case SL_PP_WHITESPACE:
158 i++;
159 break;
160
161 case SL_PP_NEWLINE:
162 line++;
163 /* pass thru */
164 case SL_PP_EOF:
165 i++;
166 *tokens_eaten = i;
167 context->line = line;
168 found_end = 1;
169 break;
170
171 default:
172 /* Expected end of line. */
173 return -1;
174 }
175 }
176 }
177
178 /* Should not get here. */
179 }