1 #include <cstdio>
2 #include <cstring>
3 #include <sstream>
4 #include <string>
5 using namespace std;
6
7 #include "keywords.h"
8 #include "parseColor.h"
9 #include "xpUtil.h"
10
11 // sloppy, but it's an easy way to set the comment marker as a line
12 // terminator
13 static bool commentEndsLine = true;
14
15 bool
isDelimiter(char c)16 isDelimiter(char c)
17 {
18 return(c == ' ' || c == '\t');
19 }
20
21 bool
isEndOfLine(char c)22 isEndOfLine(char c)
23 {
24 // 13 is DOS end-of-line, 28 is the file separator
25 bool returnValue = (c == '\0' || c == 13 || c == 28);
26
27 if (commentEndsLine) returnValue = (c == '#' || returnValue);
28
29 return(returnValue);
30 }
31
32 static void
skipPastToken(int & i,const char * line,const char endChar)33 skipPastToken(int &i, const char *line, const char endChar)
34 {
35 while (line[i] != endChar)
36 {
37 if (isEndOfLine(line[i]))
38 {
39 ostringstream errStr;
40 errStr << "Malformed line:\n\t" << line << "\n";
41 xpWarn(errStr.str(), __FILE__, __LINE__);
42
43 return;
44 }
45 i++;
46 }
47 }
48
49 static void
skipPastToken(int & i,const char * line)50 skipPastToken(int &i, const char *line)
51 {
52 while (!isDelimiter(line[i]))
53 {
54 if (isEndOfLine(line[i])) return;
55 i++;
56 }
57 }
58
59 // If the line contains 'key', return everything between 'key' and 'endChar'
60 static bool
getValue(const char * line,int & i,const char * key,const char endChar,char * & returnstring)61 getValue(const char *line, int &i, const char *key, const char endChar,
62 char *&returnstring)
63 {
64 const unsigned int length = strlen(key);
65 if (strncmp(line + i, key, length) == 0)
66 {
67 i += length;
68 int istart = i;
69 skipPastToken(i, line, endChar);
70 returnstring = new char[i - istart + 1];
71 strncpy(returnstring, (line + istart), i - istart);
72 returnstring[i-istart] = '\0';
73 i++;
74 return(true);
75 }
76 return(false);
77 }
78
79 // If the line contains 'key', return everything between 'key' and
80 // 'endChar' comment markers are allowed in the string. Use this for
81 // reading marker labels.
82 static bool
getValueIncludingComment(const char * line,int & i,const char * key,const char endChar,char * & returnstring)83 getValueIncludingComment(const char *line, int &i, const char *key,
84 const char endChar, char *&returnstring)
85 {
86 commentEndsLine = false;
87 bool returnValue = getValue(line, i, key, endChar, returnstring);
88 commentEndsLine = true;
89 return(returnValue);
90 }
91
92 static bool
getValueAfter(const char * line,int & i,const char * key,const char endChar,char * & returnstring)93 getValueAfter(const char *line, int &i, const char *key, const char endChar,
94 char *&returnstring)
95 // If the line contains the 'key', skip past 'endChar' and return
96 // everything to the end of the line in 'returnString'
97 {
98 const unsigned int length = strlen(key);
99 if (strncmp(line + i, key, length) == 0)
100 {
101 i += length;
102 skipPastToken(i, line, endChar); // Skips 'to' endChar
103 int istart = i + 1; // Add another to not include endChar
104 skipPastToken(i, line);
105 returnstring = new char[i - istart + 1];
106 strncpy(returnstring, (line + istart), i - istart);
107 returnstring[i-istart] = '\0';
108 i++;
109 return(true);
110 }
111 return(false);
112 }
113
114 static bool
getValue(const char * line,int & i,const char * key,char * & returnstring)115 getValue(const char *line, int &i, const char *key, char *&returnstring)
116 {
117 const unsigned int length = strlen(key);
118 if (strncmp(line + i, key, length) == 0)
119 {
120 i += length;
121 int istart = i;
122 skipPastToken(i, line);
123 returnstring = new char[i - istart + 1];
124 strncpy(returnstring, (line + istart), i - istart);
125 returnstring[i-istart] = '\0';
126 i++;
127 return(true);
128 }
129 return(false);
130 }
131
132 // This routine returns the next token in the line and its type.
133 int
parse(int & i,const char * line,char * & returnString)134 parse(int &i, const char *line, char *&returnString)
135 {
136 if (i >= (int) strlen(line)) return(ENDOFLINE);
137
138 if (returnString != NULL)
139 xpWarn("returnString is not NULL!\n", __FILE__, __LINE__);
140
141 int returnVal = UNKNOWN;
142
143 if (isDelimiter(line[i]))
144 {
145 i++;
146 returnVal = DELIMITER;
147 }
148 else if (isEndOfLine(line[i]))
149 returnVal = ENDOFLINE;
150 else if (getValue(line, i, "align=", returnString))
151 returnVal = ALIGN;
152 else if (getValue(line, i, "arc_color={", '}', returnString))
153 returnVal = ARC_COLOR;
154 else if (getValue(line, i, "arc_color=", returnString))
155 {
156 unsigned char RGB[3];
157 parseColor(returnString, RGB);
158 delete [] returnString;
159 returnString = new char[32];
160 snprintf(returnString, 32, "%d,%d,%d", RGB[0], RGB[1], RGB[2]);
161 returnVal = ARC_COLOR;
162 }
163 else if (getValue(line, i, "arc_thickness=", returnString))
164 returnVal = THICKNESS;
165 // This line must be after all other "arc_" keywords, because it
166 // gobbles all forms
167 else if (getValueAfter(line, i, "arc_", '=', returnString))
168 returnVal = ARC_FILE;
169 else if (getValue(line, i, "[", ']', returnString))
170 returnVal = BODY;
171 else if (getValue(line, i, "altcirc=", returnString))
172 returnVal = CIRCLE;
173 else if (getValue(line, i, "circle=", returnString))
174 returnVal = CIRCLE;
175 else if (getValue(line, i, "bump_map=", returnString))
176 returnVal = BUMP_MAP;
177 else if (getValue(line, i, "bump_scale=", returnString))
178 returnVal = BUMP_SCALE;
179 else if (getValue(line, i, "bump_shade=", returnString))
180 returnVal = BUMP_SHADE;
181 else if (getValue(line, i, "cloud_gamma=", returnString))
182 returnVal = CLOUD_GAMMA;
183 else if (getValue(line, i, "cloud_map=", returnString))
184 returnVal = CLOUD_MAP;
185 else if (getValue(line, i, "cloud_ssec=", returnString))
186 returnVal = CLOUD_SSEC;
187 else if (getValue(line, i, "cloud_threshold=", returnString))
188 returnVal = CLOUD_THRESHOLD;
189 else if (getValue(line, i, "color={", '}', returnString))
190 returnVal = COLOR;
191 else if (getValue(line, i, "color=", returnString))
192 {
193 unsigned char RGB[3];
194 parseColor(returnString, RGB);
195 delete [] returnString;
196 returnString = new char[32];
197 snprintf(returnString, 32, "%d,%d,%d", RGB[0], RGB[1], RGB[2]);
198 returnVal = COLOR;
199 }
200 else if (getValue(line, i, "draw_orbit=", returnString))
201 returnVal = DRAW_ORBIT;
202 else if (getValue(line, i, "font=", returnString))
203 returnVal = FONT;
204 else if (getValue(line, i, "fontsize=", returnString))
205 returnVal = FONTSIZE;
206 else if (getValue(line, i, "grid=", returnString))
207 returnVal = GRID;
208 else if (getValue(line, i, "grid1=", returnString))
209 returnVal = GRID1;
210 else if (getValue(line, i, "grid2=", returnString))
211 returnVal = GRID2;
212 else if (getValue(line, i, "grid_color=", returnString))
213 returnVal = GRID_COLOR;
214 else if (getValue(line, i, "image=", returnString))
215 returnVal = IMAGE;
216 else if (getValue(line, i, "lang=", returnString))
217 returnVal = LANGUAGE;
218 else if (getValue(line, i, "magnify=", returnString))
219 returnVal = MAGNIFY;
220 else if (getValue(line, i, "mapbounds={", '}', returnString))
221 returnVal = MAP_BOUNDS;
222 else if (getValue(line, i, "marker_color={", '}', returnString))
223 returnVal = MARKER_COLOR;
224 else if (getValue(line, i, "marker_color=", returnString))
225 {
226 unsigned char RGB[3];
227 parseColor(returnString, RGB);
228 delete [] returnString;
229 returnString = new char[32];
230 snprintf(returnString, 32, "%d,%d,%d", RGB[0], RGB[1], RGB[2]);
231 returnVal = MARKER_COLOR;
232 }
233 else if (getValue(line, i, "marker_font=", returnString))
234 returnVal = MARKER_FONT;
235 else if (getValue(line, i, "marker_fontsize=", returnString))
236 returnVal = MARKER_FONTSIZE;
237 // This line must be after all other "marker_" keywords, because
238 // it gobbles all forms
239 else if (getValueAfter(line, i, "marker_", '=', returnString))
240 returnVal = MARKER_FILE;
241 else if (getValue(line, i, "map=", returnString))
242 returnVal = DAY_MAP;
243 else if (getValue(line, i, "max_radius_for_label=", returnString))
244 returnVal = MAX_RAD_FOR_LABEL;
245 else if (getValue(line, i, "min_radius_for_label=", returnString))
246 returnVal = MIN_RAD_FOR_LABEL;
247 else if (getValue(line, i, "min_radius_for_markers=", returnString))
248 returnVal = MIN_RAD_FOR_MARKERS;
249 else if (getValue(line, i, "max_radius=", returnString))
250 returnVal = MAX_RAD_FOR_MARKERS;
251 else if (getValue(line, i, "min_radius=", returnString))
252 returnVal = MIN_RAD_FOR_MARKERS;
253 else if (getValueIncludingComment(line, i, "\"", '"', returnString))
254 returnVal = NAME;
255 else if (getValueIncludingComment(line, i, "{", '}', returnString))
256 returnVal = NAME;
257 else if (getValue(line, i, "night_map=", returnString))
258 returnVal = NIGHT_MAP;
259 else if (getValue(line, i, "orbit={", '}', returnString))
260 returnVal = ORBIT;
261 else if (getValue(line, i, "orbit_color={", '}', returnString))
262 returnVal = ORBIT_COLOR;
263 else if (getValue(line, i, "orbit_color=", returnString))
264 {
265 unsigned char RGB[3];
266 parseColor(returnString, RGB);
267 delete [] returnString;
268 returnString = new char[32];
269 snprintf(returnString, 32, "%d,%d,%d", RGB[0], RGB[1], RGB[2]);
270 returnVal = ORBIT_COLOR;
271 }
272 else if (getValue(line, i, "relative_to=", returnString))
273 returnVal = ORIGIN;
274 else if (getValue(line, i, "opacity=", returnString))
275 returnVal = OPACITY;
276 else if (getValue(line, i, "outlined=", returnString))
277 returnVal = OUTLINED;
278 else if (getValue(line, i, "position=", returnString))
279 returnVal = POSITION;
280 else if (getValue(line, i, "radius=", returnString))
281 returnVal = RADIUS;
282 else if (getValue(line, i, "random_origin=", returnString))
283 returnVal = RANDOM_ORIGIN;
284 else if (getValue(line, i, "random_target=", returnString))
285 returnVal = RANDOM_TARGET;
286 else if (getValue(line, i, "rayleigh_emission_weight=", returnString))
287 returnVal = RAYLEIGH_EMISSION_WEIGHT;
288 else if (getValue(line, i, "rayleigh_file=", returnString))
289 returnVal = RAYLEIGH_FILE;
290 else if (getValue(line, i, "rayleigh_limb_scale=", returnString))
291 returnVal = RAYLEIGH_LIMB_SCALE;
292 else if (getValue(line, i, "rayleigh_scale=", returnString))
293 returnVal = RAYLEIGH_SCALE;
294 // Any 'new' satellite_* tokens must be before this, because it
295 // gobbles all forms
296 else if (getValueAfter(line, i, "satellite_", '=', returnString))
297 returnVal = SATELLITE_FILE;
298 else if (getValue(line, i, "shade=", returnString))
299 returnVal = SHADE;
300 else if (getValue(line, i, "spacing=", returnString))
301 returnVal = SPACING;
302 else if (getValue(line, i, "specular_map=", returnString))
303 returnVal = SPECULAR_MAP;
304 else if (getValue(line, i, "symbolsize=", returnString))
305 returnVal = SYMBOLSIZE;
306 else if (getValue(line, i, "text_color={", '}', returnString))
307 returnVal = TEXT_COLOR;
308 else if (getValue(line, i, "thickness=", returnString))
309 returnVal = THICKNESS;
310 else if (strncmp(line+i, "timezone=", 9) == 0)
311 {
312 i += 9;
313 int istart = i;
314 while (line[i] == '/' || line[i] == ',' || !isDelimiter(line[i]))
315 {
316 if (isEndOfLine(line[i])) break;
317 i++;
318 }
319 returnString = new char[i - istart + 1];
320 strncpy(returnString, (line + istart), i - istart);
321 returnString[i-istart] = '\0';
322 returnVal = TIMEZONE;
323 }
324 else if (getValue(line, i, "trail={", '}', returnString))
325 returnVal = TRAIL;
326 else if (getValue(line, i, "trail_output=", returnString))
327 returnVal = OUTPUT;
328 else if (getValue(line, i, "transparent={", '}', returnString))
329 returnVal = TRANSPARENT;
330 else if (getValue(line, i, "twilight=", returnString))
331 returnVal = TWILIGHT;
332 else // assume it's a latitude/longitude value
333 {
334 int istart = i;
335 skipPastToken(i, line);
336 returnString = new char[i - istart + 1];
337 strncpy(returnString, (line + istart), i - istart);
338 returnString[i-istart] = '\0';
339
340 returnVal = LATLON;
341 }
342
343 return(returnVal);
344 }
345