changeset 117:36552c7d7171

Merged.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 15 Feb 2016 15:24:17 +0200
parents 9a0aeb9ce9ba (current diff) d062312ea850 (diff)
children 24583e5ca0b3
files
diffstat 1 files changed, 151 insertions(+), 171 deletions(-) [+]
line wrap: on
line diff
--- a/sidinfo.c	Mon Feb 15 07:00:22 2016 +0200
+++ b/sidinfo.c	Mon Feb 15 15:24:17 2016 +0200
@@ -1,6 +1,6 @@
 /*
  * SIDInfo - PSID/RSID information displayer
- * Written by Matti 'ccr' Hämäläinen <ccr@tnsp.org>
+ * Written by Matti 'ccr' Hämäläinen <ccr@tnsp.org>
  * (C) Copyright 2014-2016 Tecnic Software productions (TNSP)
  */
 #include "th_args.h"
@@ -12,35 +12,11 @@
 // Some constants
 #define SET_SLDB_FILENAME "Songlengths.txt"
 
-
-// Flags for various information fields
 enum
 {
-    SIF_NONE           = 0,
-
-    SIF_TYPE           = 0x00000001,
-    SIF_VERSION        = 0x00000002,
-    SIF_DATA_OFFS      = 0x00000004,
-    SIF_LOAD_ADDR      = 0x00000008,
-    SIF_INIT_ADDR      = 0x00000010,
-    SIF_PLAY_ADDR      = 0x00000020,
-    SIF_SONGS          = 0x00000040,
-    SIF_START_SONG     = 0x00000080,
-    SIF_SPEEDS         = 0x00000100,
-    SIF_SID_NAME       = 0x00000200,
-    SIF_SID_AUTHOR     = 0x00000400,
-    SIF_SID_COPYRIGHT  = 0x00000800,
-    SIF_PLAYER_TYPE    = 0x00001000,
-    SIF_PLAYSID_TUNE   = 0x00002000,
-    SIF_VIDEO_CLOCK    = 0x00004000,
-    SIF_SID_MODEL      = 0x00008000,
-    SIF_SONGLENGTHS    = 0x00010000,
-
-    SIF_DATA_SIZE      = 0x00100000,
-    SIF_HASH           = 0x00200000,
-    SIF_FILENAME       = 0x01000000,
-
-    SIF_ALL            = 0x0fffffff,
+    OTYPE_OTHER    = 0,
+    OTYPE_STR      = 1,
+    OTYPE_INT      = 2,
 };
 
 
@@ -49,6 +25,7 @@
     int cmd;
     char *str;
     char chr;
+    int flags;
 } PSFStackItem;
 
 
@@ -61,40 +38,39 @@
 
 typedef struct
 {
-    uint32_t flag;
     char *name;
     char *lname;
+    int type;
 } PSFOption;
 
 
-static const PSFOption optPSFlags[] =
+static const PSFOption optPSOptions[] =
 {
-    { SIF_FILENAME       , "Filename"   , NULL },
-    { SIF_TYPE           , "Type"       , NULL },
-    { SIF_VERSION        , "Version"    , NULL },
-    { SIF_PLAYER_TYPE    , "PlayerType" , "Player type" },
-    { SIF_PLAYSID_TUNE   , "PlayerCompat", "Player compatibility" },
-    { SIF_VIDEO_CLOCK    , "VideoClock" , "Video clock speed" },
-    { SIF_SID_MODEL      , "SIDModel"   , "SID model" },
+    { "Filename"     , NULL                   , OTYPE_STR },
+    { "Type"         , NULL                   , OTYPE_STR },
+    { "Version"      , NULL                   , OTYPE_STR },
+    { "PlayerType"   , "Player type"          , OTYPE_STR },
+    { "PlayerCompat" , "Player compatibility" , OTYPE_STR },
+    { "VideoClock"   , "Video clock speed"    , OTYPE_STR },
+    { "SIDModel"     , "SID model"            , OTYPE_STR },
 
-    { SIF_DATA_OFFS      , "DataOffs"   , "Data offset" },
-    { SIF_DATA_SIZE      , "DataSize"   , "Data size" },
-    { SIF_LOAD_ADDR      , "LoadAddr"   , "Load address" },
-    { SIF_INIT_ADDR      , "InitAddr"   , "Init address" },
-    { SIF_PLAY_ADDR      , "PlayAddr"   , "Play address" },
-    { SIF_SONGS          , "Songs"      , "Songs" },
-    { SIF_START_SONG     , "StartSong"  , "Start song" },
-    { SIF_SID_NAME       , "Name"       , NULL },
-    { SIF_SID_AUTHOR     , "Author"     , NULL },
-    { SIF_SID_COPYRIGHT  , "Copyright"  , NULL },
-    { SIF_HASH           , "Hash"       , NULL },
+    { "DataOffs"     , "Data offset"          , OTYPE_INT },
+    { "DataSize"     , "Data size"            , OTYPE_INT },
+    { "LoadAddr"     , "Load address"         , OTYPE_INT },
+    { "InitAddr"     , "Init address"         , OTYPE_INT },
+    { "PlayAddr"     , "Play address"         , OTYPE_INT },
+    { "Songs"        , "Songs"                , OTYPE_INT },
+    { "StartSong"    , "Start song"           , OTYPE_INT },
 
-    { SIF_SONGLENGTHS    , "Songlengths", "Song lengths" },
+    { "Name"         , NULL                   , OTYPE_STR },
+    { "Author"       , NULL                   , OTYPE_STR },
+    { "Copyright"    , NULL                   , OTYPE_STR },
+    { "Hash"         , NULL                   , OTYPE_OTHER },
 
-    { SIF_ALL            , "All"        , NULL },
+    { "Songlengths"  , "Song lengths"         , OTYPE_OTHER },
 };
 
-static const int noptPSFlags = sizeof(optPSFlags) / sizeof(optPSFlags[0]);
+static const int noptPSOptions = sizeof(optPSOptions) / sizeof(optPSOptions[0]);
 
 
 // Option variables
@@ -103,9 +79,9 @@
 BOOL	optParsable = FALSE,
         optNoNamePrefix = FALSE,
         optHexadecimal = FALSE,
-        optOneLine = FALSE;
+        optOneLine = FALSE,
+        optFieldOutput = TRUE;
 char    *optFieldSep = NULL;
-uint32_t optFields = SIF_ALL;
 int     optNFiles = 0;
 
 PSFStack optFormat;
@@ -141,16 +117,16 @@
         "\n"
         "Available fields:\n");
 
-    for (len = index = 0; index < noptPSFlags; index++)
+    for (len = index = 0; index < noptPSOptions; index++)
     {
-        const PSFOption *opt = &optPSFlags[index];
+        const PSFOption *opt = &optPSOptions[index];
         len += strlen(opt->name) + 3;
         if (len >= 72)
         {
             printf("\n");
             len = 0;
         }
-        printf("%s%s", opt->name, (index < noptPSFlags - 1) ? ", " : "\n\n");
+        printf("%s%s", opt->name, (index < noptPSOptions - 1) ? ", " : "\n\n");
     }
 
     printf(
@@ -169,9 +145,9 @@
 int argMatchPSField(const char *field)
 {
     int index, found = -1;
-    for (index = 0; index < noptPSFlags; index++)
+    for (index = 0; index < noptPSOptions; index++)
     {
-        const PSFOption *opt = &optPSFlags[index];
+        const PSFOption *opt = &optPSOptions[index];
         if (th_strcasecmp(opt->name, field) == 0)
         {
             if (found >= 0)
@@ -201,25 +177,6 @@
 }
 
 
-BOOL argParsePSField(char *opt, char *end, uint32_t *fields)
-{
-    // Trim whitespace
-    if (end != NULL)
-        while (end > opt && *end && th_isspace(*end)) end--;
-
-    while (*opt && th_isspace(*opt)) opt++;
-
-    // Match field name
-    char *field = (end != NULL) ? th_strndup(opt, end - opt) : th_strdup(opt);
-    int found = argMatchPSFieldError(field);
-    if (found >= 0)
-        *fields |= optPSFlags[found].flag;
-
-    th_free(field);
-    return FALSE;
-}
-
-
 BOOL siStackAddItem(PSFStack *stack, const PSFStackItem *item)
 {
     if (stack->items == NULL || stack->nitems + 1 >= stack->nallocated)
@@ -257,6 +214,40 @@
 }
 
 
+BOOL argParsePSFields(PSFStack *stack, const char *fmt)
+{
+    const char *start = fmt;
+    siClearStack(stack);
+
+    while (*start)
+    {
+        PSFStackItem item;
+        const char *end = strchr(start, ',');
+        char *field = (end != NULL) ?
+            th_strndup_trim(start, end - start, TH_TRIM_BOTH) :
+            th_strdup_trim(start, TH_TRIM_BOTH);
+
+        int found = argMatchPSFieldError(field);
+        th_free(field);
+
+        if (found < 0)
+            return FALSE;
+
+        item.cmd = found;
+        item.str = NULL;
+        if (!siStackAddItem(stack, &item))
+            return FALSE;
+
+        if (!end)
+            break;
+
+        start = end + 1;
+    }
+
+    return TRUE;
+}
+
+
 //
 // Parse a format string into a PSFStack structure
 //
@@ -265,6 +256,7 @@
     PSFStackItem item;
     const char *start = NULL;
     int mode = 0;
+    BOOL rval = TRUE;
 
     siClearStack(stack);
 
@@ -298,19 +290,18 @@
                 }
                 else
                 {
-                    char *field = th_strndup(start, fmt - start);
+                    char *field = th_strndup_trim(start, fmt - start, TH_TRIM_BOTH);
                     int ret = argMatchPSFieldError(field);
+                    th_free(field);
                     if (ret >= 0)
                     {
                         item.cmd = ret;
                         item.str = NULL;
                         if (!siStackAddItem(stack, &item))
-                        {
-                            th_free(field);
                             return FALSE;
-                        }
                     }
-                    th_free(field);
+                    else
+                        rval = FALSE;
                 }
                 mode = 0;
             }
@@ -335,7 +326,7 @@
             break;
     }
 
-    return TRUE;
+    return rval;
 }
 
 
@@ -357,23 +348,8 @@
         break;
 
     case 3:
-        {
-            char *start = optArg;
-            optFields = SIF_NONE;
-
-            while (*start)
-            {
-                char *end = strchr(start, ',');
-
-                if (!argParsePSField(start, end, &optFields))
-                    return FALSE;
-
-                if (!end)
-                    break;
-
-                start = end + 1;
-            }
-        }
+        if (!argParsePSFields(&optFormat, optArg))
+            return FALSE;
         break;
 
     case 4:
@@ -390,6 +366,7 @@
         break;
 
     case 7:
+        optFieldOutput = FALSE;
         if (!argParsePSFormatStr(&optFormat, optArg))
             return FALSE;
         break;
@@ -435,44 +412,42 @@
 static void siPrintFieldPrefix(FILE *outFile, const PSFOption *opt)
 {
     const char *name = (optParsable || opt->lname == NULL) ? opt->name : opt->lname;
-    if (!optNoNamePrefix && !optFormat.nitems)
+    if (!optNoNamePrefix && optFieldOutput)
         fprintf(outFile, optParsable ? "%s=" : "%-20s : ", name);
 }
 
 
 static void siPrintFieldSeparator(FILE *outFile)
 {
-    if (!optFormat.nitems)
+    if (optFieldOutput)
         fputs(optOneLine ? optFieldSep : "\n", outFile);
 }
 
 
 static void siPrintPSIDInfoLine(FILE *outFile, BOOL *shown, const int xindex, const char *xfmt, const char *xaltfmt, ...)
 {
-    const PSFOption *opt = &optPSFlags[xindex];
-    if (optFormat.nitems || (optFields & opt->flag))
-    {
-        va_list ap;
-        const char *fmt = optHexadecimal ? (xaltfmt != NULL ? xaltfmt : xfmt) : xfmt;
+    const PSFOption *opt = &optPSOptions[xindex];
+    va_list ap;
+    const char *fmt = optHexadecimal ? (xaltfmt != NULL ? xaltfmt : xfmt) : xfmt;
 
-        siPrintFieldPrefix(outFile, opt);
+    siPrintFieldPrefix(outFile, opt);
 
-        va_start(ap, xaltfmt);
-        vfprintf(outFile, fmt, ap);
-        va_end(ap);
+    va_start(ap, xaltfmt);
+    vfprintf(outFile, fmt, ap);
+    va_end(ap);
 
-        siPrintFieldSeparator(outFile);
-        *shown = TRUE;
-    }
+    siPrintFieldSeparator(outFile);
+    *shown = TRUE;
 }
 
 
 #define PR(xfmt, xaltfmt, ...) siPrintPSIDInfoLine(outFile, shown, xindex, xfmt, xaltfmt, __VA_ARGS__ )
 
 
-static void siPrintPSIDInformationField(FILE *outFile, const char *filename, const PSIDHeader *psid, BOOL *shown, const int xindex)
+static void siPrintPSIDInformationField(FILE *outFile, const char *filename, const PSIDHeader *psid, BOOL *shown, const PSFStackItem *item)
 {
-    switch (xindex)
+    const PSFOption *opt = &optPSOptions[item->cmd];
+    switch (item->cmd)
     {
         case  0: PR("%s", NULL, filename); break;
         case  1: PR("%s", NULL, psid->magic); break;
@@ -503,38 +478,25 @@
         case 16: PR("%s", NULL, psid->sidCopyright); break;
 
         case 17:
-            {
-                const PSFOption *opt = &optPSFlags[xindex];
-                if (optFormat.nitems || (optFields & opt->flag))
-                {
-                    siPrintFieldPrefix(outFile, opt);
-                    th_md5_print(outFile, psid->hash);
-                    siPrintFieldSeparator(outFile);
-                }
-            }
+            siPrintFieldPrefix(outFile, opt);
+            th_md5_print(outFile, psid->hash);
+            siPrintFieldSeparator(outFile);
             break;
 
         case 18:
+            siPrintFieldPrefix(outFile, opt);
+            if (psid->lengths != NULL)
             {
-                const PSFOption *opt = &optPSFlags[xindex];
-                if (optFormat.nitems || (optFields & opt->flag))
+                int i;
+                for (i = 0; i < psid->lengths->nlengths; i++)
                 {
-                    siPrintFieldPrefix(outFile, opt);
-                    if (psid->lengths != NULL)
-                    {
-                        int i;
-                        for (i = 0; i < psid->lengths->nlengths; i++)
-                        {
-                            int len = psid->lengths->lengths[i];
-                            fprintf(outFile, "%d:%d%s", len / 60, len % 60,
-                                (i < psid->lengths->nlengths - 1) ? " " : "");
-                        }
-                    }
-                    siPrintFieldSeparator(outFile);
+                    int len = psid->lengths->lengths[i];
+                    fprintf(outFile, "%d:%d%s", len / 60, len % 60,
+                        (i < psid->lengths->nlengths - 1) ? " " : "");
                 }
             }
+            siPrintFieldSeparator(outFile);
             break;
-
     }
 }
 
@@ -568,32 +530,27 @@
         psid.lengths = si_sldb_get_by_hash(sidSLDB, psid.hash);
 
     // Output
-    if (optFormat.nitems)
+    for (index = 0; index < optFormat.nitems; index++)
     {
-        for (index = 0; index < optFormat.nitems; index++)
+        PSFStackItem *item = &optFormat.items[index];
+        switch (item->cmd)
         {
-            PSFStackItem *item = &optFormat.items[index];
-            switch (item->cmd)
-            {
-                case -1:
-                    siPrintStrEscapes(outFile, item->str);
-                    break;
+            case -1:
+                siPrintStrEscapes(outFile, item->str);
+                break;
 
-                case -2:
-                    fputc(item->chr, outFile);
-                    break;
+            case -2:
+                fputc(item->chr, outFile);
+                break;
 
-                default:
-                    siPrintPSIDInformationField(outFile, filename, &psid, &shown, item->cmd);
-                    break;
-            }
+            default:
+                siPrintPSIDInformationField(outFile, filename, &psid, &shown, item);
+                break;
         }
     }
-    else
+    
+    if (optFieldOutput)
     {
-        for (index = 0; index < noptPSFlags - 1; index++)
-            siPrintPSIDInformationField(outFile, filename, &psid, &shown, index);
-
         if (shown && optOneLine)
             fprintf(outFile, "\n");
     }
@@ -624,6 +581,19 @@
         optParsable = FALSE;
         optNoNamePrefix = TRUE;
     }
+    
+    if (optFieldOutput && !optFormat.nitems)
+    {
+        PSFStackItem item;
+        int i;
+        memset(&item, 0, sizeof(item));
+        siClearStack(&optFormat);
+        for (i = 0; i < noptPSOptions; i++)
+        {
+            item.cmd = i;
+            siStackAddItem(&optFormat, &item);
+        }
+    }
 
     // Check paths
     if (setHVSCPath != NULL)
@@ -635,29 +605,39 @@
     if (setSLDBPath != NULL)
     {
         // Initialize SLDB
-        int ret;
-        th_ioctx *ctx;
+        int ret = THERR_OK;
+        th_ioctx *ctx = NULL;
         if ((ctx = th_io_fopen(&th_stdio_io_ops, setSLDBPath, "r")) == NULL)
         {
-            THERR("Could not open SLDB '%s'.\n", setSLDBPath);
-            goto out;
+            THERR("Could not open SLDB '%s'.\n",
+                setSLDBPath);
+            goto err;
         }
 
-        if ((sidSLDB = si_sldb_new()) == NULL ||
-            si_sldb_read(ctx, sidSLDB) != THERR_OK)
+        THMSG(1, "Reading SLDB.\n");
+        if ((sidSLDB = si_sldb_new()) == NULL)
         {
-            THERR("Error parsing SLDB.\n");
-            th_io_close(ctx);
-            goto out;
+            THERR("Could not allocate SLDB structure!\n");
+            goto err;
+        }
+
+        if ((ret = si_sldb_read(ctx, sidSLDB)) != THERR_OK)
+        {
+            THERR("Error parsing SLDB: %d, %s\n",
+                ret, th_error_str(ret));
+            goto err;
         }
         th_io_close(ctx);
 
         if ((ret = si_sldb_build_index(sidSLDB)) != THERR_OK)
         {
-            THERR("Error building SLDB index: %s.\n",
-                th_error_str(ret));
-            goto out;
+            THERR("Error building SLDB index: %d, %s.\n",
+                ret, th_error_str(ret));
+            goto err;
         }
+
+err:
+        th_io_close(ctx);
     }
 
     // Process files