blob: 6577b77e6aaab549f81a12bd809524bcb1afd552 [file] [log] [blame]
Jonathan Gordonbdb6bf52010-05-28 05:25:48 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: tag_table.c 26346 2010-05-28 02:30:27Z jdgordon $
9 *
10 * Copyright (C) 2010 Jonathan Gordon
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
Jonathan Gordone7ef9352010-05-27 15:35:22 +000022#include <stdio.h>
23#include <stdlib.h>
24#include <stdbool.h>
25#include <string.h>
Jonathan Gordon57ad6f92010-06-02 09:51:03 +000026#include <ctype.h>
Jonathan Gordone7ef9352010-05-27 15:35:22 +000027#include "tag_table.h"
28
29#define PUTCH(out, c) fprintf(out, "%c", c)
30extern struct tag_info legal_tags[];
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +000031
Jonathan Gordon04130c22010-05-29 09:35:05 +000032char images_with_subimages[100];
33int image_count = 0;
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +000034
35/** Command line setting **/
36bool is_mono_display = false;
Jonathan Gordon68f4d912010-05-30 11:54:52 +000037bool use_new_vp_tags = true;
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +000038
39
Jonathan Gordone7ef9352010-05-27 15:35:22 +000040/* dump "count" args to output replacing '|' with ',' except after the last count.
41 * return the amount of chars read. (start+return will be after the last | )
42 */
43int dump_arg(FILE* out, const char* start, int count, bool close)
44{
45 int l = 0;
46 while (count)
47 {
48 if (start[l] == '|')
49 {
50 if (count > 1)
51 {
Jonathan Gordonfc333552010-05-27 15:55:39 +000052 PUTCH(out, ',');
Jonathan Gordone7ef9352010-05-27 15:35:22 +000053 } else if (close) {
Jonathan Gordonfc333552010-05-27 15:55:39 +000054 PUTCH(out, ')');
Jonathan Gordone7ef9352010-05-27 15:35:22 +000055 }
56 count--;
57 } else {
Jonathan Gordonbbe6c5a2010-06-02 08:18:47 +000058 if (find_escape_character(start[l]))
59 {
60 PUTCH(out, '%');
61 }
Jonathan Gordone7ef9352010-05-27 15:35:22 +000062 PUTCH(out, start[l]);
63 }
64 l++;
65 }
66 return l;
67}
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +000068
Jonathan Gordon68f4d912010-05-30 11:54:52 +000069int dump_viewport_tags(FILE* out, const char* start)
70{
71 int len = 0;
72 if (is_mono_display)
73 {
74 return dump_arg(out, start, 5, true);
75 }
76 else
77 {
78 int arg_count = use_new_vp_tags?5:7;
79 len += dump_arg(out, start, arg_count, true);
80 if (!use_new_vp_tags)
81 return len;
82 if (start[len] != '-')
83 {
84 fprintf(out, "%%Vf(");
85 len += dump_arg(out, start+len, 1, true);
86 }
87 else
88 {
89 while (start[len++] != '|');
90 }
91 if (start[len] != '-')
92 {
93 fprintf(out, "%%Vb(");
94 len += dump_arg(out, start+len, 1, true);
95 }
96 else
97 {
98 while (start[len++] != '|');
99 }
100 }
101 return len;
102}
103
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000104#define MATCH(s) (!strcmp(tag->name, s))
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000105int parse_tag(FILE* out, const char* start, bool in_conditional)
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000106{
107 struct tag_info *tag;
108 int len = 0;
109 for(tag = legal_tags;
110 tag->name[0] && strncmp(start, tag->name, strlen(tag->name)) != 0;
111 tag++) ;
112 if (!tag->name[0])
113 return -1;
114 if (tag->params[0] == '\0')
115 {
116 fprintf(out, "%s", tag->name);
117 return strlen(tag->name);
118 }
119 fprintf(out, "%s", tag->name);
120 len += strlen(tag->name);
121 start += len;
122 /* handle individual tags which accept params */
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000123 if ((MATCH("bl") || MATCH("pb") || MATCH("pv")) && !in_conditional)
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000124 {
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000125 if (*start == '|')
126 {
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000127 len++; start++;
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000128 PUTCH(out, '(');
129 /* TODO: need to verify that we are actually using the long form... */
130 len += dump_arg(out, start, 5, true);
131 }
132 }
133 else if (MATCH("d") || MATCH("D") || MATCH("mv") || MATCH("pS") || MATCH("pE") || MATCH("t") || MATCH("Tl"))
134 {
135 char temp[8] = {'\0'};
136 int i = 0;
137 /* tags which maybe have a number after them */
138 while ((*start >= '0' && *start <= '9') || *start == '.')
139 {
140 temp[i++] = *start++;
141 }
142 if (i!= 0)
143 {
144 fprintf(out, "(%s)", temp);
145 len += i;
146 }
147 }
148 else if (MATCH("xl"))
149 {
Jonathan Gordon04130c22010-05-29 09:35:05 +0000150 char label = start[1];
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000151 PUTCH(out, '(');
Jonathan Gordon9262a832010-05-28 03:06:51 +0000152 int read = 1+dump_arg(out, start+1, 4, false);
153 len += read;
154 start += read;
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000155 if (*start>= '0' && *start <= '9')
156 {
Jonathan Gordon04130c22010-05-29 09:35:05 +0000157 images_with_subimages[image_count++] = label;
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000158 PUTCH(out, ',');
159 len += dump_arg(out, start, 1, false);
160 }
161 PUTCH(out, ')');
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000162 }
163 else if (MATCH("xd"))
164 {
Jonathan Gordon04130c22010-05-29 09:35:05 +0000165 char label = start[0];
166 int i=0;
167 while (i<image_count)
168 {
169 if (images_with_subimages[i] == label)
170 break;
171 i++;
172 }
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000173 PUTCH(out, '(');
174 PUTCH(out, *start++); len++;
Jonathan Gordon04130c22010-05-29 09:35:05 +0000175 if (i<image_count &&
176 ((*start >= 'a' && *start <= 'z') ||
177 (*start >= 'A' && *start <= 'Z')))
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000178 {
179 PUTCH(out, *start); len++;
180 }
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000181 PUTCH(out, ')');
182 }
183 else if (MATCH("x"))
184 {
185 PUTCH(out, '(');
186 len += 1+dump_arg(out, start+1, 4, true);
187 }
188 else if (MATCH("Fl"))
189 {
190 PUTCH(out, '(');
191 len += 1+dump_arg(out, start+1, 2, true);
192 }
193 else if (MATCH("Cl"))
194 {
Jonathan Gordon57ad6f92010-06-02 09:51:03 +0000195 int read;
196 char xalign = '\0', yalign = '\0';
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000197 PUTCH(out, '(');
Jonathan Gordon57ad6f92010-06-02 09:51:03 +0000198 read = 1+dump_arg(out, start+1, 2, false);
199 len += read;
200 start += read;
201 switch (tolower(*start))
202 {
203 case 'l':
204 case 'c':
205 case 'r':
206 case '+':
207 case '-':
208 xalign = *start;
209 len++;
210 start++;
211 break;
212 case 'd':
213 case 'D':
214 case 'i':
215 case 'I':
216 case 's':
217 case 'S':
218 len++;
219 start++;
220 break;
221 }
222 PUTCH(out,',');
223 read = dump_arg(out, start, 1, false);
224 len += read;
225 start += read;
226 switch (tolower(*start))
227 {
228 case 't':
229 case 'c':
230 case 'b':
231 case '+':
232 case '-':
233 yalign = *start;
234 len++;
235 start++;
236 break;
237 case 'd':
238 case 'D':
239 case 'i':
240 case 'I':
241 case 's':
242 case 'S':
243 len++;
244 start++;
245 break;
246 }
247 PUTCH(out,',');
248 read = dump_arg(out, start, 1, false);
249 if (xalign)
250 {
251 if (xalign == '-')
252 xalign = 'l';
253 if (xalign == '+')
254 xalign = 'r';
255 fprintf(out, ",%c", xalign);
256 }
257 if (yalign)
258 {
259 if (yalign == '-')
260 yalign = 't';
261 if (yalign == '+')
262 yalign = 'b';
263 fprintf(out, ",%s%c", xalign?"":"-,", yalign);
264 }
265 PUTCH(out, ')');
266 len += read;
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000267 }
268 else if (MATCH("Vd") || MATCH("VI"))
269 {
270 PUTCH(out, '(');
271 PUTCH(out, *start); len++;
272 PUTCH(out, ')');
273 }
274 else if (MATCH("Vp"))
275 {
276 /* NOTE: almost certainly needs work */
277 PUTCH(out, '(');
278 len += 1+dump_arg(out, start+1, 3, true);
279 }
280 else if (MATCH("Vl") || MATCH("Vi"))
281 {
Jonathan Gordon68f4d912010-05-30 11:54:52 +0000282 int read;
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000283 PUTCH(out, '(');
Jonathan Gordon68f4d912010-05-30 11:54:52 +0000284 read = 1+dump_arg(out, start+1, 1, false);
285 PUTCH(out, ',');
286 len += read + dump_viewport_tags(out, start+read);
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000287 }
288 else if (MATCH("V"))
289 {
290 PUTCH(out, '(');
Jonathan Gordon68f4d912010-05-30 11:54:52 +0000291 len += 1+dump_viewport_tags(out, start+1);
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000292 }
293 else if (MATCH("X"))
294 {
295 if (*start+1 == 'd')
296 {
297 fprintf(out, "(d)");
298 len ++;
299 }
300 else
301 {
302 PUTCH(out, '(');
303 len += 1+dump_arg(out, start+1, 1, true);
304 }
305 }
306 else if (MATCH("St") || MATCH("Sx"))
307 {
308 PUTCH(out, '(');
309 len += 1+dump_arg(out, start+1, 1, true);
310 }
311
312 else if (MATCH("T"))
313 {
314 PUTCH(out, '(');
315 len += 1+dump_arg(out, start+1, 5, true);
316 }
317 return len;
318}
319
320void parse_text(const char* in, FILE* out)
321{
322 const char* end = in+strlen(in);
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000323 int level = 0;
324 int len;
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000325top:
326 while (in < end && *in)
327 {
328 if (*in == '%')
329 {
330 PUTCH(out, *in++);
331 switch(*in)
332 {
333
334 case '%':
335 case '<':
336 case '|':
337 case '>':
338 case ';':
339 case '#':
Jonathan Gordonbbe6c5a2010-06-02 08:18:47 +0000340 case ')':
341 case '(':
342 case ',':
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000343 PUTCH(out, *in++);
344 goto top;
345 break;
346 case '?':
347 PUTCH(out, *in++);
348 break;
349 }
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000350 len = parse_tag(out, in, level>0);
351 if (len < 0)
352 {
353 PUTCH(out, *in++);
354 }
355 else
356 {
357 in += len;
358 }
359 }
360 else if (*in == '<')
361 {
362 level++;
363 PUTCH(out, *in++);
364 }
365 else if (*in == '>')
366 {
367 level--;
368 PUTCH(out, *in++);
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000369 }
Jonathan Gordonbbe6c5a2010-06-02 08:18:47 +0000370 else if (*in == '|')
371 {
372 if (level == 0)
373 {
374 PUTCH(out, '%');
375 }
376 PUTCH(out, *in++);
377 }
Jonathan Gordonfc333552010-05-27 15:55:39 +0000378 else if (*in == '#')
379 {
Jonathan Gordon8cd3f842010-05-29 09:09:45 +0000380 while (*in && *in != '\n')
Jonathan Gordonfc333552010-05-27 15:55:39 +0000381 {
382 PUTCH(out, *in++);
383 }
384 }
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000385 else
386 {
Jonathan Gordonbbe6c5a2010-06-02 08:18:47 +0000387 if (find_escape_character(*in))
388 {
389 PUTCH(out, '%');
390 }
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000391 PUTCH(out, *in++);
392 }
393 }
394}
395
396int main(int argc, char* argv[])
397{
Jonathan Gordon4e0f7f62010-05-27 15:47:32 +0000398 char buffer[10*1024], temp[512];
399 FILE *in, *out = stdout;
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000400 int filearg = 1, i=0;
Jonathan Gordon4e0f7f62010-05-27 15:47:32 +0000401 if( (argc < 2) ||
402 strcmp(argv[1],"-h") == 0 ||
403 strcmp(argv[1],"--help") == 0 )
404 {
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000405 printf("Usage: %s [OPTIONS] infile [outfile]\n", argv[0]);
406 printf("\nOPTIONS:\n");
Jonathan Gordon68f4d912010-05-30 11:54:52 +0000407 printf("\t-c\tDon't use new viewport colour tags (non-mono displays only)\n");
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000408 printf("\t-m\tSkin is for a mono display (different viewport tags)\n");
Jonathan Gordon4e0f7f62010-05-27 15:47:32 +0000409 return 0;
410 }
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000411
412 while ((argc > filearg) && argv[filearg][0] == '-')
413 {
414 i=1;
415 while (argv[filearg][i])
416 {
417 switch(argv[filearg][i])
418 {
Jonathan Gordon68f4d912010-05-30 11:54:52 +0000419 case 'c': /* disable new colour tags */
420 use_new_vp_tags = false;
421 break;
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000422 case 'm': /* skin is for a mono display */
423 is_mono_display = true;
424 break;
425 }
426 i++;
427 }
428 filearg++;
429 }
430 if (argc == filearg)
431 {
432 printf("Missing input filename\n");
433 return 1;
434 }
435
436 in = fopen(argv[filearg], "r");
Jonathan Gordon4e0f7f62010-05-27 15:47:32 +0000437 if (!in)
438 return 1;
439 while (fgets(temp, 512, in))
440 strcat(buffer, temp);
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000441 fclose(in);
442 filearg++;
Jonathan Gordon4e0f7f62010-05-27 15:47:32 +0000443
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000444 if (argc > filearg)
Jonathan Gordon4e0f7f62010-05-27 15:47:32 +0000445 {
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000446 out = fopen(argv[filearg], "w");
Jonathan Gordon4e0f7f62010-05-27 15:47:32 +0000447 if (!out)
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000448 {
449 printf("Couldn't open %s\n", argv[filearg]);
Jonathan Gordon4e0f7f62010-05-27 15:47:32 +0000450 return 1;
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000451 }
Jonathan Gordon4e0f7f62010-05-27 15:47:32 +0000452 }
453
454 parse_text(buffer, out);
Jonathan Gordon4e0f7f62010-05-27 15:47:32 +0000455 if (out != stdout)
456 fclose(out);
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000457 return 0;
458}