9ac4b44610
NEW PARSER: add an 'N' param type which will accept any number of strings, will cause very big problems if this isnt the last param for a tag. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26727 a1c6a512-1295-4272-9138-f99709370657
525 lines
13 KiB
C
525 lines
13 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id: tag_table.c 26346 2010-05-28 02:30:27Z jdgordon $
|
|
*
|
|
* Copyright (C) 2010 Jonathan Gordon
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include "tag_table.h"
|
|
|
|
#define PUTCH(out, c) fprintf(out, "%c", c)
|
|
extern struct tag_info legal_tags[];
|
|
|
|
char images_with_subimages[100];
|
|
int image_count = 0;
|
|
|
|
/** Command line setting **/
|
|
bool is_mono_display = false;
|
|
bool use_new_vp_tags = true;
|
|
|
|
|
|
/* dump "count" args to output replacing '|' with ',' except after the last count.
|
|
* return the amount of chars read. (start+return will be after the last | )
|
|
*/
|
|
int dump_arg(FILE* out, const char* start, int count, bool close)
|
|
{
|
|
int l = 0;
|
|
while (count)
|
|
{
|
|
if (start[l] == '|')
|
|
{
|
|
if (count > 1)
|
|
{
|
|
PUTCH(out, ',');
|
|
} else if (close) {
|
|
PUTCH(out, ')');
|
|
}
|
|
count--;
|
|
} else {
|
|
if (find_escape_character(start[l]))
|
|
{
|
|
PUTCH(out, '%');
|
|
}
|
|
PUTCH(out, start[l]);
|
|
}
|
|
l++;
|
|
}
|
|
return l;
|
|
}
|
|
|
|
int dump_viewport_tags(FILE* out, const char* start)
|
|
{
|
|
int len = 0;
|
|
if (is_mono_display)
|
|
{
|
|
return dump_arg(out, start, 5, true);
|
|
}
|
|
else
|
|
{
|
|
int arg_count = use_new_vp_tags?5:7;
|
|
len += dump_arg(out, start, arg_count, true);
|
|
if (!use_new_vp_tags)
|
|
return len;
|
|
if (start[len] != '-')
|
|
{
|
|
fprintf(out, "%%Vf(");
|
|
len += dump_arg(out, start+len, 1, true);
|
|
}
|
|
else
|
|
{
|
|
while (start[len++] != '|');
|
|
}
|
|
if (start[len] != '-')
|
|
{
|
|
fprintf(out, "%%Vb(");
|
|
len += dump_arg(out, start+len, 1, true);
|
|
}
|
|
else
|
|
{
|
|
while (start[len++] != '|');
|
|
}
|
|
}
|
|
return len;
|
|
}
|
|
|
|
#define MATCH(s) (!strcmp(tag->name, s))
|
|
int parse_tag(FILE* out, const char* start, bool in_conditional)
|
|
{
|
|
struct tag_info *tag;
|
|
int len = 0;
|
|
for(tag = legal_tags;
|
|
tag->name[0] && strncmp(start, tag->name, strlen(tag->name)) != 0;
|
|
tag++) ;
|
|
if (!tag->name[0])
|
|
return -1;
|
|
if (tag->params[0] == '\0')
|
|
{
|
|
fprintf(out, "%s", tag->name);
|
|
return strlen(tag->name);
|
|
}
|
|
if (!strcmp(tag->name, "C"))
|
|
{
|
|
fprintf(out, "Cd");
|
|
return 1;
|
|
}
|
|
|
|
fprintf(out, "%s", tag->name);
|
|
len += strlen(tag->name);
|
|
start += len;
|
|
/* handle individual tags which accept params */
|
|
if ((MATCH("bl") || MATCH("pb") || MATCH("pv")) && !in_conditional)
|
|
{
|
|
if (*start == '|')
|
|
{
|
|
int i=0;
|
|
char filename[128];
|
|
len++; start++;
|
|
PUTCH(out, '(');
|
|
/* |file|x|y|width|height| -> (x,y,width,height,file) */
|
|
while (start[i] != '|')
|
|
{
|
|
filename[i] = start[i];
|
|
i++;
|
|
}
|
|
filename[i] = '\0';
|
|
len +=i+1;
|
|
start += i+1;
|
|
/* TODO: need to verify that we are actually using the long form... */
|
|
len += dump_arg(out, start, 4, false);
|
|
if (i>0)
|
|
{
|
|
fprintf(out, ",%s", filename);
|
|
}
|
|
PUTCH(out, ')');
|
|
}
|
|
}
|
|
else if (MATCH("d") || MATCH("D") || MATCH("mv") || MATCH("pS") || MATCH("pE") || MATCH("t") || MATCH("Tl"))
|
|
{
|
|
char temp[8] = {'\0'};
|
|
int i = 0;
|
|
/* tags which maybe have a number after them */
|
|
while ((*start >= '0' && *start <= '9') || *start == '.')
|
|
{
|
|
temp[i++] = *start++;
|
|
}
|
|
if (i!= 0)
|
|
{
|
|
fprintf(out, "(%s)", temp);
|
|
len += i;
|
|
}
|
|
}
|
|
else if (MATCH("xl"))
|
|
{
|
|
char label = start[1];
|
|
PUTCH(out, '(');
|
|
int read = 1+dump_arg(out, start+1, 4, false);
|
|
len += read;
|
|
start += read;
|
|
if (*start>= '0' && *start <= '9')
|
|
{
|
|
images_with_subimages[image_count++] = label;
|
|
PUTCH(out, ',');
|
|
len += dump_arg(out, start, 1, false);
|
|
}
|
|
PUTCH(out, ')');
|
|
}
|
|
else if (MATCH("xd"))
|
|
{
|
|
char label = start[0];
|
|
int i=0;
|
|
while (i<image_count)
|
|
{
|
|
if (images_with_subimages[i] == label)
|
|
break;
|
|
i++;
|
|
}
|
|
PUTCH(out, '(');
|
|
PUTCH(out, *start++); len++;
|
|
if (i<image_count &&
|
|
((*start >= 'a' && *start <= 'z') ||
|
|
(*start >= 'A' && *start <= 'Z')))
|
|
{
|
|
PUTCH(out, *start); len++;
|
|
}
|
|
PUTCH(out, ')');
|
|
}
|
|
else if (MATCH("x"))
|
|
{
|
|
PUTCH(out, '(');
|
|
len += 1+dump_arg(out, start+1, 4, true);
|
|
}
|
|
else if (MATCH("Fl"))
|
|
{
|
|
PUTCH(out, '(');
|
|
len += 1+dump_arg(out, start+1, 2, true);
|
|
}
|
|
else if (MATCH("Cl"))
|
|
{
|
|
int read;
|
|
char xalign = '\0', yalign = '\0';
|
|
PUTCH(out, '(');
|
|
read = 1+dump_arg(out, start+1, 2, false);
|
|
len += read;
|
|
start += read;
|
|
switch (tolower(*start))
|
|
{
|
|
case 'l':
|
|
case 'c':
|
|
case 'r':
|
|
case '+':
|
|
case '-':
|
|
xalign = *start;
|
|
len++;
|
|
start++;
|
|
break;
|
|
case 'd':
|
|
case 'D':
|
|
case 'i':
|
|
case 'I':
|
|
case 's':
|
|
case 'S':
|
|
len++;
|
|
start++;
|
|
break;
|
|
}
|
|
PUTCH(out,',');
|
|
read = dump_arg(out, start, 1, false);
|
|
len += read;
|
|
start += read;
|
|
switch (tolower(*start))
|
|
{
|
|
case 't':
|
|
case 'c':
|
|
case 'b':
|
|
case '+':
|
|
case '-':
|
|
yalign = *start;
|
|
len++;
|
|
start++;
|
|
break;
|
|
case 'd':
|
|
case 'D':
|
|
case 'i':
|
|
case 'I':
|
|
case 's':
|
|
case 'S':
|
|
len++;
|
|
start++;
|
|
break;
|
|
}
|
|
PUTCH(out,',');
|
|
read = dump_arg(out, start, 1, false);
|
|
if (xalign)
|
|
{
|
|
if (xalign == '-')
|
|
xalign = 'l';
|
|
if (xalign == '+')
|
|
xalign = 'r';
|
|
fprintf(out, ",%c", xalign);
|
|
}
|
|
if (yalign)
|
|
{
|
|
if (yalign == '-')
|
|
yalign = 't';
|
|
if (yalign == '+')
|
|
yalign = 'b';
|
|
fprintf(out, ",%s%c", xalign?"":"-,", yalign);
|
|
}
|
|
PUTCH(out, ')');
|
|
len += read;
|
|
}
|
|
else if (MATCH("Vd") || MATCH("VI"))
|
|
{
|
|
PUTCH(out, '(');
|
|
PUTCH(out, *start); len++;
|
|
PUTCH(out, ')');
|
|
}
|
|
else if (MATCH("Vp"))
|
|
{
|
|
int read;
|
|
/* NOTE: almost certainly needs work */
|
|
PUTCH(out, '(');
|
|
read = 1+dump_arg(out, start+1, 1, false);
|
|
PUTCH(out, ',');
|
|
while (start[read] != '|')
|
|
{
|
|
PUTCH(out, start[read++]);
|
|
}
|
|
PUTCH(out, ',');
|
|
read++;
|
|
while (start[read] != '|')
|
|
{
|
|
PUTCH(out, start[read++]);
|
|
}
|
|
PUTCH(out, ')');
|
|
read++;
|
|
len += read;
|
|
}
|
|
else if (MATCH("Vi"))
|
|
{
|
|
int read = 1;
|
|
|
|
PUTCH(out, '(');
|
|
if ((start[1] >= 'a' && start[1] <= 'z') ||
|
|
(start[1] >= 'A' && start[1] <= 'Z'))
|
|
{
|
|
read = 1+dump_arg(out, start+1, 1, false);
|
|
}
|
|
else
|
|
{
|
|
PUTCH(out, '-');
|
|
}
|
|
PUTCH(out, ',');
|
|
len += read + dump_viewport_tags(out, start+read);
|
|
}
|
|
else if (MATCH("Vl") || MATCH("Vi"))
|
|
{
|
|
int read;
|
|
PUTCH(out, '(');
|
|
read = 1+dump_arg(out, start+1, 1, false);
|
|
PUTCH(out, ',');
|
|
len += read + dump_viewport_tags(out, start+read);
|
|
}
|
|
else if (MATCH("V"))
|
|
{
|
|
PUTCH(out, '(');
|
|
len += 1+dump_viewport_tags(out, start+1);
|
|
}
|
|
else if (MATCH("X"))
|
|
{
|
|
if (*start == 'd')
|
|
{
|
|
fprintf(out, "(d)");
|
|
len ++;
|
|
}
|
|
else
|
|
{
|
|
PUTCH(out, '(');
|
|
len += 1+dump_arg(out, start+1, 1, true);
|
|
}
|
|
}
|
|
else if (MATCH("St") || MATCH("Sx"))
|
|
{
|
|
PUTCH(out, '(');
|
|
len += 1+dump_arg(out, start+1, 1, true);
|
|
}
|
|
|
|
else if (MATCH("T"))
|
|
{
|
|
PUTCH(out, '(');
|
|
len += 1+dump_arg(out, start+1, 5, true);
|
|
}
|
|
return len;
|
|
}
|
|
|
|
void parse_text(const char* in, FILE* out)
|
|
{
|
|
const char* end = in+strlen(in);
|
|
int level = 0;
|
|
int len;
|
|
top:
|
|
while (in < end && *in)
|
|
{
|
|
if (*in == '%')
|
|
{
|
|
PUTCH(out, *in++);
|
|
switch(*in)
|
|
{
|
|
|
|
case '%':
|
|
case '<':
|
|
case '|':
|
|
case '>':
|
|
case ';':
|
|
case '#':
|
|
case ')':
|
|
case '(':
|
|
case ',':
|
|
PUTCH(out, *in++);
|
|
goto top;
|
|
break;
|
|
case '?':
|
|
if (in[1] == 'C' && in[2] == '<')
|
|
{
|
|
fprintf(out, "?C");
|
|
in += 2;
|
|
goto top;
|
|
}
|
|
else
|
|
{
|
|
PUTCH(out, *in++);
|
|
}
|
|
break;
|
|
}
|
|
len = parse_tag(out, in, level>0);
|
|
if (len < 0)
|
|
{
|
|
PUTCH(out, *in++);
|
|
}
|
|
else
|
|
{
|
|
in += len;
|
|
}
|
|
}
|
|
else if (*in == '<')
|
|
{
|
|
level++;
|
|
PUTCH(out, *in++);
|
|
}
|
|
else if (*in == '>')
|
|
{
|
|
level--;
|
|
PUTCH(out, *in++);
|
|
}
|
|
else if (*in == '|')
|
|
{
|
|
if (level == 0)
|
|
{
|
|
PUTCH(out, '%');
|
|
}
|
|
PUTCH(out, *in++);
|
|
}
|
|
else if (*in == '#')
|
|
{
|
|
while (*in && *in != '\n')
|
|
{
|
|
PUTCH(out, *in++);
|
|
}
|
|
}
|
|
else if (*in == ';')
|
|
{
|
|
PUTCH(out, *in++);
|
|
}
|
|
else
|
|
{
|
|
if (find_escape_character(*in))
|
|
{
|
|
PUTCH(out, '%');
|
|
}
|
|
PUTCH(out, *in++);
|
|
}
|
|
}
|
|
}
|
|
|
|
int main(int argc, char* argv[])
|
|
{
|
|
char buffer[10*1024], temp[512];
|
|
FILE *in, *out = stdout;
|
|
int filearg = 1, i=0;
|
|
if( (argc < 2) ||
|
|
strcmp(argv[1],"-h") == 0 ||
|
|
strcmp(argv[1],"--help") == 0 )
|
|
{
|
|
printf("Usage: %s [OPTIONS] infile [outfile]\n", argv[0]);
|
|
printf("\nOPTIONS:\n");
|
|
printf("\t-c\tDon't use new viewport colour tags (non-mono displays only)\n");
|
|
printf("\t-m\tSkin is for a mono display (different viewport tags)\n");
|
|
return 0;
|
|
}
|
|
|
|
while ((argc > filearg) && argv[filearg][0] == '-')
|
|
{
|
|
i=1;
|
|
while (argv[filearg][i])
|
|
{
|
|
switch(argv[filearg][i])
|
|
{
|
|
case 'c': /* disable new colour tags */
|
|
use_new_vp_tags = false;
|
|
break;
|
|
case 'm': /* skin is for a mono display */
|
|
is_mono_display = true;
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
filearg++;
|
|
}
|
|
if (argc == filearg)
|
|
{
|
|
printf("Missing input filename\n");
|
|
return 1;
|
|
}
|
|
|
|
in = fopen(argv[filearg], "r");
|
|
if (!in)
|
|
return 1;
|
|
while (fgets(temp, 512, in))
|
|
strcat(buffer, temp);
|
|
fclose(in);
|
|
filearg++;
|
|
|
|
if (argc > filearg)
|
|
{
|
|
out = fopen(argv[filearg], "w");
|
|
if (!out)
|
|
{
|
|
printf("Couldn't open %s\n", argv[filearg]);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
parse_text(buffer, out);
|
|
if (out != stdout)
|
|
fclose(out);
|
|
return 0;
|
|
}
|