cueprint now passes the conversion specification on to printf, so it handles flags, width, and precision.
This commit is contained in:
265
tools/cueprint.c
265
tools/cueprint.c
@@ -16,6 +16,8 @@
|
|||||||
#define D_TEMPLATE "%P \"%T\" (%N tracks)\n"
|
#define D_TEMPLATE "%P \"%T\" (%N tracks)\n"
|
||||||
#define T_TEMPLATE "%n: %p \"%t\"\n"
|
#define T_TEMPLATE "%n: %p \"%t\"\n"
|
||||||
|
|
||||||
|
#define UNSPECIFIED -1
|
||||||
|
|
||||||
char *progname;
|
char *progname;
|
||||||
char *d_template = D_TEMPLATE; /* disc template */
|
char *d_template = D_TEMPLATE; /* disc template */
|
||||||
char *t_template = T_TEMPLATE; /* track template */
|
char *t_template = T_TEMPLATE; /* track template */
|
||||||
@@ -67,41 +69,55 @@ Any other %<character> is expanded to that character. For example, to get a\n\
|
|||||||
exit (status);
|
exit (status);
|
||||||
}
|
}
|
||||||
|
|
||||||
void disc_field (char *c, Cd *cd)
|
void disc_field (char *conv, int length, Cd *cd)
|
||||||
{
|
{
|
||||||
|
char *c; /* pointer to conversion character */
|
||||||
|
|
||||||
Cdtext *cdtext = NULL;
|
Cdtext *cdtext = NULL;
|
||||||
cdtext = cd_get_cdtext(cd);
|
cdtext = cd_get_cdtext(cd);
|
||||||
|
|
||||||
|
c = conv + length - 1;
|
||||||
|
|
||||||
switch (*c) {
|
switch (*c) {
|
||||||
case 'A':
|
case 'A':
|
||||||
printf("%s", cdtext_get(PTI_ARRANGER, cdtext));
|
*c = 's';
|
||||||
|
printf(conv, cdtext_get(PTI_ARRANGER, cdtext));
|
||||||
break;
|
break;
|
||||||
case 'C':
|
case 'C':
|
||||||
printf("%s", cdtext_get(PTI_COMPOSER, cdtext));
|
*c = 's';
|
||||||
|
printf(conv, cdtext_get(PTI_COMPOSER, cdtext));
|
||||||
break;
|
break;
|
||||||
case 'G':
|
case 'G':
|
||||||
printf("%s", cdtext_get(PTI_GENRE, cdtext));
|
*c = 's';
|
||||||
|
printf(conv, cdtext_get(PTI_GENRE, cdtext));
|
||||||
break;
|
break;
|
||||||
case 'M':
|
case 'M':
|
||||||
printf("%s", cdtext_get(PTI_MESSAGE, cdtext));
|
*c = 's';
|
||||||
|
printf(conv, cdtext_get(PTI_MESSAGE, cdtext));
|
||||||
break;
|
break;
|
||||||
case 'N':
|
case 'N':
|
||||||
printf("%0*d", 2, cd_get_ntrack(cd));
|
*c = 'd';
|
||||||
|
printf(conv, cd_get_ntrack(cd));
|
||||||
break;
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
printf("%s", cdtext_get(PTI_PERFORMER, cdtext));
|
*c = 's';
|
||||||
|
printf(conv, cdtext_get(PTI_PERFORMER, cdtext));
|
||||||
break;
|
break;
|
||||||
case 'R':
|
case 'R':
|
||||||
printf("%s", cdtext_get(PTI_ARRANGER, cdtext));
|
*c = 's';
|
||||||
|
printf(conv, cdtext_get(PTI_ARRANGER, cdtext));
|
||||||
break;
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
printf("%s", cdtext_get(PTI_SONGWRITER, cdtext));
|
*c = 's';
|
||||||
|
printf(conv, cdtext_get(PTI_SONGWRITER, cdtext));
|
||||||
break;
|
break;
|
||||||
case 'T':
|
case 'T':
|
||||||
printf("%s", cdtext_get(PTI_TITLE, cdtext));
|
*c = 's';
|
||||||
|
printf(conv, cdtext_get(PTI_TITLE, cdtext));
|
||||||
break;
|
break;
|
||||||
case 'U':
|
case 'U':
|
||||||
printf("%s", cdtext_get(PTI_UPC_ISRC, cdtext));
|
*c = 's';
|
||||||
|
printf(conv, cdtext_get(PTI_UPC_ISRC, cdtext));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
putchar(*c);
|
putchar(*c);
|
||||||
@@ -109,122 +125,199 @@ void disc_field (char *c, Cd *cd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void track_field (char *c, Cd *cd, int trackno, int width)
|
void track_field (char *conv, int length, Cd *cd, int trackno)
|
||||||
{
|
{
|
||||||
|
char *c; /* pointer to conversion character */
|
||||||
|
|
||||||
Track *track = NULL;
|
Track *track = NULL;
|
||||||
Cdtext *cdtext = NULL;
|
Cdtext *cdtext = NULL;
|
||||||
|
|
||||||
track = cd_get_track(cd, trackno);
|
track = cd_get_track(cd, trackno);
|
||||||
cdtext = track_get_cdtext(track);
|
cdtext = track_get_cdtext(track);
|
||||||
|
|
||||||
|
c = conv + length - 1;
|
||||||
|
|
||||||
switch (*c) {
|
switch (*c) {
|
||||||
case 'a':
|
case 'a':
|
||||||
printf("%*s", width, cdtext_get(PTI_ARRANGER, cdtext));
|
*c = 's';
|
||||||
|
printf(conv, cdtext_get(PTI_ARRANGER, cdtext));
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
printf("%*s", width, cdtext_get(PTI_COMPOSER, cdtext));
|
*c = 's';
|
||||||
|
printf(conv, cdtext_get(PTI_COMPOSER, cdtext));
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
printf("%*s", width, track_get_filename(track));
|
*c = 's';
|
||||||
|
printf(conv, track_get_filename(track));
|
||||||
break;
|
break;
|
||||||
case 'g':
|
case 'g':
|
||||||
printf("%*s", width, cdtext_get(PTI_GENRE, cdtext));
|
*c = 's';
|
||||||
|
printf(conv, cdtext_get(PTI_GENRE, cdtext));
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
printf("%*s", width, track_get_isrc(track));
|
*c = 's';
|
||||||
|
printf(conv, track_get_isrc(track));
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
printf("%*s", width, cdtext_get(PTI_MESSAGE, cdtext));
|
*c = 's';
|
||||||
|
printf(conv, cdtext_get(PTI_MESSAGE, cdtext));
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
printf("%0*d", width, trackno);
|
*c = 'd';
|
||||||
|
printf(conv, trackno);
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
printf("%*s", width, cdtext_get(PTI_PERFORMER, cdtext));
|
*c = 's';
|
||||||
|
printf(conv, cdtext_get(PTI_PERFORMER, cdtext));
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
printf("%*s", width, cdtext_get(PTI_SONGWRITER, cdtext));
|
*c = 's';
|
||||||
|
printf(conv, cdtext_get(PTI_SONGWRITER, cdtext));
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
printf("%*s", width, cdtext_get(PTI_TITLE, cdtext));
|
*c = 's';
|
||||||
|
printf(conv, cdtext_get(PTI_TITLE, cdtext));
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
printf("%*s", width, cdtext_get(PTI_UPC_ISRC, cdtext));
|
*c = 's';
|
||||||
|
printf(conv, cdtext_get(PTI_UPC_ISRC, cdtext));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
disc_field(c, cd);
|
disc_field(conv, length, cd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_info (Cd *cd)
|
/* print a % conversion specification
|
||||||
|
* %[flag(s)][width][.precision]<conversion-char>
|
||||||
|
*/
|
||||||
|
void print_conv (char *start, int length, Cd *cd, int trackno)
|
||||||
|
{
|
||||||
|
char *conv; /* copy of conversion specification */
|
||||||
|
|
||||||
|
/* TODO: use strndup? */
|
||||||
|
conv = malloc ((unsigned) (length + 1));
|
||||||
|
strncpy(conv, start, length);
|
||||||
|
conv[length] = '\0';
|
||||||
|
|
||||||
|
/* conversion character */
|
||||||
|
if (0 == trackno)
|
||||||
|
disc_field(conv, length, cd);
|
||||||
|
else
|
||||||
|
track_field(conv, length, cd, trackno);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* print an escaped character
|
||||||
|
* `c' is the character after the `/'
|
||||||
|
* NOTE: this does not handle octal and hexidecimal escapes
|
||||||
|
*/
|
||||||
|
int print_esc (char *c)
|
||||||
|
{
|
||||||
|
/* ?, ', " are handled by the default */
|
||||||
|
switch (*c) {
|
||||||
|
case 'a':
|
||||||
|
putchar('\a');
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
putchar('\b');
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
putchar('\f');
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
putchar('\n');
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
putchar('\r');
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
putchar('\t');
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
putchar('\v');
|
||||||
|
break;
|
||||||
|
case '0':
|
||||||
|
putchar('\0');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
putchar(*c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cd_printf (char *format, Cd *cd, int trackno)
|
||||||
|
{
|
||||||
|
char *c; /* pointer into format */
|
||||||
|
char *conv_start;
|
||||||
|
int conv_length;
|
||||||
|
|
||||||
|
for (c = format; '\0' != *c; c++) {
|
||||||
|
switch (*c) {
|
||||||
|
case '%':
|
||||||
|
conv_start = c;
|
||||||
|
conv_length = 1;
|
||||||
|
c++;
|
||||||
|
|
||||||
|
/* flags */
|
||||||
|
while ( \
|
||||||
|
'-' == *c \
|
||||||
|
|| '+' == *c \
|
||||||
|
|| ' ' == *c \
|
||||||
|
|| '0' == *c \
|
||||||
|
|| '#' == *c \
|
||||||
|
) {
|
||||||
|
conv_length++;
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* field width */
|
||||||
|
/* '*' not recognized */
|
||||||
|
while (0 != isdigit(*c)) {
|
||||||
|
conv_length++;
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* precision */
|
||||||
|
/* '*' not recognized */
|
||||||
|
if ('.' == *c) {
|
||||||
|
conv_length++;
|
||||||
|
c++;
|
||||||
|
|
||||||
|
while (0 != isdigit(*c)) {
|
||||||
|
conv_length++;
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* length modifier (h, l, or L) */
|
||||||
|
/* not recognized */
|
||||||
|
|
||||||
|
/* conversion character */
|
||||||
|
conv_length++;
|
||||||
|
|
||||||
|
print_conv(conv_start, conv_length, cd, trackno);
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
c++;
|
||||||
|
|
||||||
|
print_esc(c);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
putchar(*c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_info (Cd *cd)
|
||||||
{
|
{
|
||||||
int i; /* track */
|
int i; /* track */
|
||||||
char *c;
|
char *c;
|
||||||
|
|
||||||
/* field flags */
|
cd_printf(d_template, cd, 0);
|
||||||
int flag = 1; /* flags remain */
|
|
||||||
int zeropad = 0;
|
|
||||||
|
|
||||||
/* field width */
|
|
||||||
int width;
|
|
||||||
|
|
||||||
for (c = d_template; '\0' != *c; c++) {
|
|
||||||
if ('%' == *c) {
|
|
||||||
c++;
|
|
||||||
disc_field(c, cd);
|
|
||||||
} else {
|
|
||||||
putchar(*c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 1; i <= cd_get_ntrack(cd); i++) {
|
for (i = 1; i <= cd_get_ntrack(cd); i++) {
|
||||||
for (c = t_template; '\0' != *c; c++) {
|
cd_printf(t_template, cd, i);
|
||||||
/* TODO: should apply escapes and width to disc
|
|
||||||
* template as well
|
|
||||||
*/
|
|
||||||
if ('\\' == *c) {
|
|
||||||
c++;
|
|
||||||
|
|
||||||
/* TODO: add more (all?) escapes */
|
|
||||||
switch (*c) {
|
|
||||||
case 'n':
|
|
||||||
putchar('\n');
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
putchar('\t');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
putchar(*c);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if ('%' == *c) {
|
|
||||||
c++;
|
|
||||||
|
|
||||||
/* parse flags */
|
|
||||||
/* TODO: zero-padding does nothing */
|
|
||||||
do {
|
|
||||||
switch (*c) {
|
|
||||||
case '0': /* zero-padding */
|
|
||||||
c++;
|
|
||||||
zeropad = 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
flag = 0;
|
|
||||||
}
|
|
||||||
} while (0 != flag);
|
|
||||||
|
|
||||||
/* parse width */
|
|
||||||
width = 0;
|
|
||||||
while (0 != isdigit(*c)) {
|
|
||||||
width = width * 10 + *c++ - '0';
|
|
||||||
}
|
|
||||||
|
|
||||||
track_field(c, cd, i, width);
|
|
||||||
} else {
|
|
||||||
putchar(*c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user