blob: fe7edbb81babf5a797b229958e6119b4fce622fa [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 }
Jonathan Gordon50356d82010-06-08 15:09:32 +0000119 if (!strcmp(tag->name, "C"))
120 {
121 fprintf(out, "Cd");
122 return 1;
123 }
124
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000125 fprintf(out, "%s", tag->name);
126 len += strlen(tag->name);
127 start += len;
128 /* handle individual tags which accept params */
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000129 if ((MATCH("bl") || MATCH("pb") || MATCH("pv")) && !in_conditional)
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000130 {
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000131 if (*start == '|')
132 {
Jonathan Gordon9ac4b442010-06-09 16:15:01 +0000133 int i=0;
134 char filename[128];
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000135 len++; start++;
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000136 PUTCH(out, '(');
Jonathan Gordon9ac4b442010-06-09 16:15:01 +0000137 /* |file|x|y|width|height| -> (x,y,width,height,file) */
138 while (start[i] != '|')
139 {
140 filename[i] = start[i];
141 i++;
142 }
143 filename[i] = '\0';
144 len +=i+1;
145 start += i+1;
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000146 /* TODO: need to verify that we are actually using the long form... */
Jonathan Gordon9ac4b442010-06-09 16:15:01 +0000147 len += dump_arg(out, start, 4, false);
148 if (i>0)
149 {
150 fprintf(out, ",%s", filename);
151 }
152 PUTCH(out, ')');
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000153 }
154 }
155 else if (MATCH("d") || MATCH("D") || MATCH("mv") || MATCH("pS") || MATCH("pE") || MATCH("t") || MATCH("Tl"))
156 {
157 char temp[8] = {'\0'};
158 int i = 0;
159 /* tags which maybe have a number after them */
160 while ((*start >= '0' && *start <= '9') || *start == '.')
161 {
162 temp[i++] = *start++;
163 }
164 if (i!= 0)
165 {
166 fprintf(out, "(%s)", temp);
167 len += i;
168 }
169 }
170 else if (MATCH("xl"))
171 {
Jonathan Gordon04130c22010-05-29 09:35:05 +0000172 char label = start[1];
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000173 PUTCH(out, '(');
Jonathan Gordon9262a832010-05-28 03:06:51 +0000174 int read = 1+dump_arg(out, start+1, 4, false);
175 len += read;
176 start += read;
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000177 if (*start>= '0' && *start <= '9')
178 {
Jonathan Gordon04130c22010-05-29 09:35:05 +0000179 images_with_subimages[image_count++] = label;
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000180 PUTCH(out, ',');
181 len += dump_arg(out, start, 1, false);
182 }
183 PUTCH(out, ')');
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000184 }
185 else if (MATCH("xd"))
186 {
Jonathan Gordon04130c22010-05-29 09:35:05 +0000187 char label = start[0];
188 int i=0;
189 while (i<image_count)
190 {
191 if (images_with_subimages[i] == label)
192 break;
193 i++;
194 }
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000195 PUTCH(out, '(');
196 PUTCH(out, *start++); len++;
Jonathan Gordon04130c22010-05-29 09:35:05 +0000197 if (i<image_count &&
198 ((*start >= 'a' && *start <= 'z') ||
199 (*start >= 'A' && *start <= 'Z')))
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000200 {
201 PUTCH(out, *start); len++;
202 }
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000203 PUTCH(out, ')');
204 }
205 else if (MATCH("x"))
206 {
207 PUTCH(out, '(');
208 len += 1+dump_arg(out, start+1, 4, true);
209 }
210 else if (MATCH("Fl"))
211 {
212 PUTCH(out, '(');
213 len += 1+dump_arg(out, start+1, 2, true);
214 }
215 else if (MATCH("Cl"))
216 {
Jonathan Gordon57ad6f92010-06-02 09:51:03 +0000217 int read;
218 char xalign = '\0', yalign = '\0';
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000219 PUTCH(out, '(');
Jonathan Gordon57ad6f92010-06-02 09:51:03 +0000220 read = 1+dump_arg(out, start+1, 2, false);
221 len += read;
222 start += read;
223 switch (tolower(*start))
224 {
225 case 'l':
226 case 'c':
227 case 'r':
228 case '+':
229 case '-':
230 xalign = *start;
231 len++;
232 start++;
233 break;
234 case 'd':
235 case 'D':
236 case 'i':
237 case 'I':
238 case 's':
239 case 'S':
240 len++;
241 start++;
242 break;
243 }
244 PUTCH(out,',');
245 read = dump_arg(out, start, 1, false);
246 len += read;
247 start += read;
248 switch (tolower(*start))
249 {
250 case 't':
251 case 'c':
252 case 'b':
253 case '+':
254 case '-':
255 yalign = *start;
256 len++;
257 start++;
258 break;
259 case 'd':
260 case 'D':
261 case 'i':
262 case 'I':
263 case 's':
264 case 'S':
265 len++;
266 start++;
267 break;
268 }
269 PUTCH(out,',');
270 read = dump_arg(out, start, 1, false);
271 if (xalign)
272 {
273 if (xalign == '-')
274 xalign = 'l';
275 if (xalign == '+')
276 xalign = 'r';
277 fprintf(out, ",%c", xalign);
278 }
279 if (yalign)
280 {
281 if (yalign == '-')
282 yalign = 't';
283 if (yalign == '+')
284 yalign = 'b';
285 fprintf(out, ",%s%c", xalign?"":"-,", yalign);
286 }
287 PUTCH(out, ')');
288 len += read;
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000289 }
290 else if (MATCH("Vd") || MATCH("VI"))
291 {
292 PUTCH(out, '(');
293 PUTCH(out, *start); len++;
294 PUTCH(out, ')');
295 }
296 else if (MATCH("Vp"))
297 {
Jonathan Gordon45ed0b82010-06-09 13:30:10 +0000298 int read;
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000299 /* NOTE: almost certainly needs work */
300 PUTCH(out, '(');
Jonathan Gordon45ed0b82010-06-09 13:30:10 +0000301 read = 1+dump_arg(out, start+1, 1, false);
302 PUTCH(out, ',');
303 while (start[read] != '|')
304 {
305 PUTCH(out, start[read++]);
306 }
307 PUTCH(out, ',');
308 read++;
309 while (start[read] != '|')
310 {
311 PUTCH(out, start[read++]);
312 }
313 PUTCH(out, ')');
314 read++;
315 len += read;
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000316 }
Jonathan Gordonb71dc1f2010-06-08 14:43:30 +0000317 else if (MATCH("Vi"))
318 {
319 int read = 1;
320
321 PUTCH(out, '(');
322 if ((start[1] >= 'a' && start[1] <= 'z') ||
323 (start[1] >= 'A' && start[1] <= 'Z'))
324 {
325 read = 1+dump_arg(out, start+1, 1, false);
Jonathan Gordonb71dc1f2010-06-08 14:43:30 +0000326 }
Jonathan Gordon360ed992010-06-08 14:55:37 +0000327 else
328 {
329 PUTCH(out, '-');
330 }
331 PUTCH(out, ',');
Jonathan Gordonb71dc1f2010-06-08 14:43:30 +0000332 len += read + dump_viewport_tags(out, start+read);
333 }
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000334 else if (MATCH("Vl") || MATCH("Vi"))
335 {
Jonathan Gordon68f4d912010-05-30 11:54:52 +0000336 int read;
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000337 PUTCH(out, '(');
Jonathan Gordon68f4d912010-05-30 11:54:52 +0000338 read = 1+dump_arg(out, start+1, 1, false);
339 PUTCH(out, ',');
340 len += read + dump_viewport_tags(out, start+read);
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000341 }
342 else if (MATCH("V"))
343 {
344 PUTCH(out, '(');
Jonathan Gordon68f4d912010-05-30 11:54:52 +0000345 len += 1+dump_viewport_tags(out, start+1);
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000346 }
347 else if (MATCH("X"))
348 {
Jonathan Gordonb71dc1f2010-06-08 14:43:30 +0000349 if (*start == 'd')
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000350 {
351 fprintf(out, "(d)");
352 len ++;
353 }
354 else
355 {
356 PUTCH(out, '(');
357 len += 1+dump_arg(out, start+1, 1, true);
358 }
359 }
360 else if (MATCH("St") || MATCH("Sx"))
361 {
362 PUTCH(out, '(');
363 len += 1+dump_arg(out, start+1, 1, true);
364 }
365
366 else if (MATCH("T"))
367 {
368 PUTCH(out, '(');
369 len += 1+dump_arg(out, start+1, 5, true);
370 }
371 return len;
372}
373
374void parse_text(const char* in, FILE* out)
375{
376 const char* end = in+strlen(in);
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000377 int level = 0;
378 int len;
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000379top:
380 while (in < end && *in)
381 {
382 if (*in == '%')
383 {
384 PUTCH(out, *in++);
385 switch(*in)
386 {
387
388 case '%':
389 case '<':
390 case '|':
391 case '>':
392 case ';':
393 case '#':
Jonathan Gordonbbe6c5a2010-06-02 08:18:47 +0000394 case ')':
395 case '(':
396 case ',':
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000397 PUTCH(out, *in++);
398 goto top;
399 break;
400 case '?':
Jonathan Gordon50356d82010-06-08 15:09:32 +0000401 if (in[1] == 'C' && in[2] == '<')
402 {
403 fprintf(out, "?C");
404 in += 2;
405 goto top;
406 }
407 else
408 {
409 PUTCH(out, *in++);
410 }
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000411 break;
412 }
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000413 len = parse_tag(out, in, level>0);
414 if (len < 0)
415 {
416 PUTCH(out, *in++);
417 }
418 else
419 {
420 in += len;
421 }
422 }
423 else if (*in == '<')
424 {
425 level++;
426 PUTCH(out, *in++);
427 }
428 else if (*in == '>')
429 {
430 level--;
431 PUTCH(out, *in++);
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000432 }
Jonathan Gordonbbe6c5a2010-06-02 08:18:47 +0000433 else if (*in == '|')
434 {
435 if (level == 0)
436 {
437 PUTCH(out, '%');
438 }
439 PUTCH(out, *in++);
440 }
Jonathan Gordonfc333552010-05-27 15:55:39 +0000441 else if (*in == '#')
442 {
Jonathan Gordon8cd3f842010-05-29 09:09:45 +0000443 while (*in && *in != '\n')
Jonathan Gordonfc333552010-05-27 15:55:39 +0000444 {
445 PUTCH(out, *in++);
446 }
447 }
Jonathan Gordon2309d6d2010-06-08 14:52:03 +0000448 else if (*in == ';')
449 {
450 PUTCH(out, *in++);
451 }
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000452 else
453 {
Jonathan Gordonbbe6c5a2010-06-02 08:18:47 +0000454 if (find_escape_character(*in))
455 {
456 PUTCH(out, '%');
457 }
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000458 PUTCH(out, *in++);
459 }
460 }
461}
462
463int main(int argc, char* argv[])
464{
Jonathan Gordon4e0f7f62010-05-27 15:47:32 +0000465 char buffer[10*1024], temp[512];
466 FILE *in, *out = stdout;
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000467 int filearg = 1, i=0;
Jonathan Gordon4e0f7f62010-05-27 15:47:32 +0000468 if( (argc < 2) ||
469 strcmp(argv[1],"-h") == 0 ||
470 strcmp(argv[1],"--help") == 0 )
471 {
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000472 printf("Usage: %s [OPTIONS] infile [outfile]\n", argv[0]);
473 printf("\nOPTIONS:\n");
Jonathan Gordon68f4d912010-05-30 11:54:52 +0000474 printf("\t-c\tDon't use new viewport colour tags (non-mono displays only)\n");
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000475 printf("\t-m\tSkin is for a mono display (different viewport tags)\n");
Jonathan Gordon4e0f7f62010-05-27 15:47:32 +0000476 return 0;
477 }
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000478
479 while ((argc > filearg) && argv[filearg][0] == '-')
480 {
481 i=1;
482 while (argv[filearg][i])
483 {
484 switch(argv[filearg][i])
485 {
Jonathan Gordon68f4d912010-05-30 11:54:52 +0000486 case 'c': /* disable new colour tags */
487 use_new_vp_tags = false;
488 break;
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000489 case 'm': /* skin is for a mono display */
490 is_mono_display = true;
491 break;
492 }
493 i++;
494 }
495 filearg++;
496 }
497 if (argc == filearg)
498 {
499 printf("Missing input filename\n");
500 return 1;
501 }
502
503 in = fopen(argv[filearg], "r");
Jonathan Gordon4e0f7f62010-05-27 15:47:32 +0000504 if (!in)
505 return 1;
506 while (fgets(temp, 512, in))
507 strcat(buffer, temp);
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000508 fclose(in);
509 filearg++;
Jonathan Gordon4e0f7f62010-05-27 15:47:32 +0000510
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000511 if (argc > filearg)
Jonathan Gordon4e0f7f62010-05-27 15:47:32 +0000512 {
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000513 out = fopen(argv[filearg], "w");
Jonathan Gordon4e0f7f62010-05-27 15:47:32 +0000514 if (!out)
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000515 {
516 printf("Couldn't open %s\n", argv[filearg]);
Jonathan Gordon4e0f7f62010-05-27 15:47:32 +0000517 return 1;
Jonathan Gordon20dcf0b2010-05-28 02:30:27 +0000518 }
Jonathan Gordon4e0f7f62010-05-27 15:47:32 +0000519 }
520
521 parse_text(buffer, out);
Jonathan Gordon4e0f7f62010-05-27 15:47:32 +0000522 if (out != stdout)
523 fclose(out);
Jonathan Gordone7ef9352010-05-27 15:35:22 +0000524 return 0;
525}