Commits

Anonymous committed 3739b9f

Case renaming tool and library

Comments (0)

Files changed (10)

Binary file added.
+/*
+  This case-renaming program is a simple, command-line wrapper around
+  libcaseren (or caseren.lib, depending on your platform).
+  It provides a user-interface to change an entire directory tree
+  into upper or lower case.  It defaults to lower case unless otherwise
+  specified.
+
+  Language: ANSI C with POSIX extensions
+  Author: David Dunan Ross Palmer, Daybo Logic.
+  Copyright (C) 2005, Daybo Logic, all rights reserved.
+  http://www.daybologic.co.uk/
+*/
+/*-------------------------------------------------------------------------*/
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#if defined(__BORLANDC__) && defined(HDRSTOP)
+# pragma hdrstop
+#endif
+
+#include "libcaseren.h"
+/*-------------------------------------------------------------------------*/
+#define VER_MAJ (0)
+#define VER_MIN (2)
+#define VER_PATCH (0)
+#define VER_STAMP ("20050202")
+
+static FILE *Err = NULL; /* Stream to print errors to */
+
+static struct BinOpts_t {
+  int Help, UC, LC, Recursive, Dirs, Files, Verbose, Version, AllowOptions;
+} BinOpts;
+
+static const char *RootPathName = NULL; /* As set by user */
+
+static const struct {
+  const char *ShortOpt;
+  const char *LongOpt;
+  const char *Desc;
+  const char *HelpText;
+  int *BinAddr; /* Address of binary flag */
+  const int NewBinSetting; /* New state of linked binary flag */
+} Opts[] = {
+  {
+    "h",
+    "help",
+    "Get help on syntax for calling this program",
+    "You already know how to use help, or you wouldn\'t see this message!\n",
+    &BinOpts.Help, 1
+  },
+  {
+    "u",
+    "uppercase",
+    "Convert file and directory names to upper case",
+    "This option allows you to convert all file and directory names to\n"
+    "upper case.  It may not be used with -l (--lowercase).\n"
+    "This option is mainly used for ripping DVDs.\n",
+    &BinOpts.UC, 1
+  },
+  {
+    "l",
+    "lowercase",
+    "Convert file and directory names to lower case (default)",
+    "This option allows you to convert all file and directory names to\n"
+    "lower case.  It may not be used with -u (--uppercase).\n"
+    "This option is mainly used for ripping old DOS diskettes.\n",
+    &BinOpts.LC, 1
+  },
+  {
+    "r",
+    "recursive",
+    "Recurse into sub-directories",
+    "Recurse into sub-directory trees to look for more objects to rename,\n"
+    "this does not mean the sub-directory names themselves will\n"
+    "necessarily be re-named.\n",
+    &BinOpts.Recursive, 1
+  },
+  {
+    "nd",
+    "no-dirs",
+    "Do not rename the directory names themselves",
+    "Does not rename directory names themselves but will still recurse\n"
+    "into them, looking for more objects to rename.  See -r\n"
+    "Note: -nd and -nf are mutually exclusive\n",
+    &BinOpts.Dirs, 0
+  },
+  {
+    "nf",
+    "no-files",
+    "Do not rename filenames, only the directory tree is renamed",
+    "Does not rename any files.  The directory tree is renamed but\n"
+    "all files are not renamed.  Note: -nd and -nf are mutually exclusive\n",
+    &BinOpts.Files, 0
+  },
+  {
+    "v",
+    "verbose",
+    "Show output",
+    "By default, output is only shown in case of an error, unless help\n"
+    "is requested.  -v will show the operation\'s progress.\n",
+    &BinOpts.Verbose, 1
+  },
+  {
+    NULL, /* Not applicable */
+    "version",
+    "Shows copyright and version information and exits",
+    "Shows the copyright notice for the program and all necessary version\n"
+    "and build information.  This is useful when you wish to report a bug\n"
+    "to Daybo Logic.\n",
+    &BinOpts.Version, 1
+  },
+  {
+    "--",
+    NULL, /* Not applicable */
+    "Don\'t accept further options.",
+    "Don\'t accept further options: This is useful if you have filenames\n"
+    "which begin with - or -- and may be confused for behaviour-modifying\n"
+    "options.\n",
+    NULL, 0 /* Not applicable */
+  }
+};
+
+static int mymain(const int argc, const char *argv[]);
+static void PrintLibError(enum caseren_Error ErrNo);
+static void InitBinOptions(struct BinOpts_t *PBinOpts);
+static FILE *GetErrStream(void);
+static unsigned short int PackFlags(const struct BinOpts_t *PBinOpts);
+static unsigned int TestFlags(const struct BinOpts_t *PBinOpts);
+static unsigned int ExecuteFlags(const struct BinOpts_t *PBinOpts);
+static void Help(void);
+static void Title(void);
+static void Version(void);
+/*-------------------------------------------------------------------------*/
+int main()
+{
+  static const char *testArgs[] = {
+    "caseren",
+    "--version",
+    NULL
+  };
+
+  return mymain(sizeof(testArgs)/sizeof(testArgs[0])-1, testArgs);
+}
+/*-------------------------------------------------------------------------*/
+static int mymain(const int argc, const char *argv[])
+{
+  int argi;
+  unsigned int badFlagCount;
+
+  /*
+    Parse all our command-line arguments
+  */
+  InitBinOptions(&BinOpts);
+  for ( argi = 1; argi < argc; argi++ ) {
+    if ( BinOpts.AllowOptions ) {
+      if ( argv[argi][0] == '-' ) { /* An option? */
+        int opti;
+
+        if ( argv[argi][1] == '-' && argv[argi][2] == '\0' ) {
+          BinOpts.AllowOptions = 0;
+        }
+        else {
+          int optRecog = 0; /* flag to verify recognition */
+
+          for ( opti = 0; opti < sizeof(Opts)/sizeof(Opts[0]); opti++ ) {
+            if ( argv[argi][1] == '-' ) { /* A long option? */
+              if ( Opts[opti].LongOpt ) {
+                if ( strcmp((argv[argi]+2), Opts[opti].LongOpt) == 0 ) {
+                  optRecog = 1;
+                  *(Opts[opti].BinAddr) = Opts[opti].NewBinSetting;
+                }
+              }
+            }
+            else { /* A short option */
+              if ( Opts[opti].ShortOpt ) {
+                if ( strcmp((argv[argi]+1), Opts[opti].ShortOpt) == 0 ) {
+                  optRecog = 1;
+                  *(Opts[opti].BinAddr) = Opts[opti].NewBinSetting;
+                }
+              }
+            }
+          }
+          if ( !optRecog ) {
+            fprintf(
+              GetErrStream(),
+              "Warning: Unrecognised option - \"%s\"\n",
+              argv[argi]
+            );
+          }
+        }
+      }
+      else { /* Not an option, assume path name */
+        if ( RootPathName ) {
+          fprintf(
+            GetErrStream(),
+            "Warning: More than one path name supplied, ignoring \"%s\"\n",
+            argv[argi]
+          );
+        }
+        else {
+          RootPathName = argv[argi];
+        }
+      }
+    }
+  }
+
+  badFlagCount = TestFlags(&BinOpts);
+  if ( badFlagCount ) {
+    fprintf(GetErrStream(), "Error: %u flag rules were violated\n");
+    return EXIT_FAILURE;
+  }
+
+  if ( ExecuteFlags(&BinOpts) ) {
+    enum caseren_Error err;
+    unsigned short int flags;
+
+    if ( !RootPathName ) {
+      fprintf(GetErrStream(), "Error: No path name supplied.\n");
+      return EXIT_FAILURE;
+    }
+
+    flags = PackFlags(&BinOpts);
+    err = caseren(RootPathName, flags);
+    if ( err != crSuccess ) {
+      PrintLibError(err);
+      return EXIT_FAILURE;
+    }
+  }
+
+  return EXIT_SUCCESS;
+}
+/*-------------------------------------------------------------------------*/
+static void PrintLibError(enum caseren_Error ErrNo)
+{
+  static const char *messages[] = {
+    "Not a recognised error code!!",
+    "Success",
+    "General failure",
+    "Directory depth limit reached",
+    "Illegal parameter(s) passed to library",
+    "Path name not found"
+  };
+  const char *message;
+  int internal = 0; /* To signify internal errors */
+
+  switch ( ErrNo ) {
+    case ( crSuccess ) : {
+      message = messages[1];
+      break;
+    }
+    case ( crGeneral ) : {
+      message = messages[2];
+      internal = -1;
+      break;
+    }
+    case ( crDepthLimit ) : {
+      message = messages[3];
+      break;
+    }
+    case ( crParam ) : {
+      message = messages[4];
+      internal = -1;
+      break;
+    }
+    case ( crNotFound ) : {
+      message = messages[5];
+      internal = -1;
+      break;
+    }
+    default : {
+      message = messages[0];
+      internal = -1;
+    }
+  }
+
+  fprintf(GetErrStream(), "Error (code %d): ", ErrNo);
+  if ( internal )
+    fprintf(GetErrStream(), "%s", "(internal error) ");
+
+  fprintf(GetErrStream(), "%s\n", message);
+  return;
+}
+/*-------------------------------------------------------------------------*/
+static void InitBinOptions(struct BinOpts_t *PBinOpts)
+{
+  if ( !PBinOpts ) PBinOpts = &BinOpts;
+  PBinOpts->Help = 0;
+  PBinOpts->UC = 0;
+  PBinOpts->LC = 1;
+  PBinOpts->Recursive = 0,
+  PBinOpts->Dirs = 1;
+  PBinOpts->Files = 1;
+  PBinOpts->Verbose = 0;
+  PBinOpts->Version = 0;
+  PBinOpts->AllowOptions = 1;
+  return;
+}
+/*-------------------------------------------------------------------------*/
+static FILE *GetErrStream()
+{
+  if ( !Err )
+    Err = stderr;
+
+  return Err;
+}
+/*-------------------------------------------------------------------------*/
+static unsigned short int PackFlags(const struct BinOpts_t *PBinOpts)
+{
+  unsigned short int bits = 0;
+  if ( PBinOpts->UC )
+    bits |= CASEREN_MODEBITS_UC;
+  if ( PBinOpts->Recursive )
+    bits |= CASEREN_MODEBITS_RECURSE;
+  if ( PBinOpts->Dirs )
+    bits |= CASEREN_MODEBITS_DIR;
+  if ( PBinOpts->Files )
+    bits |= CASEREN_MODEBITS_FILE;
+
+  return bits;
+}
+/*-------------------------------------------------------------------------*/
+static unsigned int TestFlags(const struct BinOpts_t *PBinOpts)
+{
+  unsigned int badFlagCount = 0U;
+  if ( !PBinOpts ) PBinOpts = &BinOpts;
+
+  if ( !PBinOpts->Files && !PBinOpts->Dirs ) {
+    fprintf(GetErrStream(), "Error: You cannot specify, -nf and -nd\n");
+    badFlagCount++;
+  }
+
+  if ( PBinOpts->UC && PBinOpts->LC ) {
+    fprintf(GetErrStream(), "Error: You cannot specific, -l and -u\n");
+    badFlagCount++;
+  }
+
+  return badFlagCount;
+}
+/*-------------------------------------------------------------------------*/
+static unsigned int ExecuteFlags(const struct BinOpts_t *PBinOpts)
+{
+  if ( !PBinOpts ) PBinOpts = &BinOpts;
+
+  if ( PBinOpts->Help ) {
+    Help();
+    return 0; /* Don't execute main library call */
+  }
+  if ( PBinOpts->Version ) {
+    Version();
+    return 0;
+  }
+
+  return 1; /* Do execute main library call */
+}
+/*-------------------------------------------------------------------------*/
+static void Help()
+{
+}
+/*-------------------------------------------------------------------------*/
+static void Title()
+{
+}
+/*-------------------------------------------------------------------------*/
+static void Version()
+{
+  struct {
+    unsigned int major;
+    unsigned int minor;
+    unsigned int patch;
+  } lib;
+
+  lib.major = caseren_Ver(&lib.minor, &lib.patch);
+
+  printf(
+    "Daybo Logic caseren version %u.%u.%u (%s)\n"
+    "Built on %s at %s\n"
+    "Daybo Logic libcaseren version %u.%u.%u (%s)\n"
+    "Built on %s at %s\n",
+    VER_MAJ,
+    VER_MIN,
+    VER_PATCH,
+    VER_STAMP,
+    __DATE__,
+    __TIME__,
+    lib.major,
+    lib.minor,
+    lib.patch,
+    caseren_VerStamp(),
+    caseren_VerBuildDate(),
+    caseren_VerBuildTime()
+  );
+}
+/*-------------------------------------------------------------------------*/
Binary file added.
Binary file added.
Binary file added.
+/****************************************************************************
+
+
+caseren.rc
+
+produced by Borland Resource Workshop
+
+
+*****************************************************************************/
+
+#define VERSIONINFO_1	1
+
+VERSIONINFO_1 VERSIONINFO 
+FILEVERSION 1, 0, 0, 0
+PRODUCTVERSION 1, 0, 0, 0
+FILEOS VOS_NT_WINDOWS32
+FILETYPE VFT_APP
+{
+ BLOCK "StringFileInfo"
+ {
+  BLOCK "040904E4"
+  {
+   VALUE "CompanyName", "Daybo Logic\000\000"
+   VALUE "FileDescription", "Simple program to change the case of a directory tree\000"
+   VALUE "FileVersion", "1.00\000\000"
+   VALUE "InternalName", "caseren\000"
+   VALUE "LegalCopyright", "Copyright � Daybo Logic 2005\000\000"
+   VALUE "OriginalFilename", "caseren.exe\000"
+   VALUE "URL", "http://www.daybologic.co.uk/\000\000"
+   VALUE "Contact", "http://www.daybologic.co.uk/mailddrp/\000"
+  }
+
+ }
+
+ BLOCK "VarFileInfo"
+ {
+  VALUE "Translation", 0x409, 1252
+ }
+
+}
+
Binary file added.
Binary file added.
+/*
+  libcaseren is the functional part of the command-line utility
+  "caseren".  It provides one, simple, user-callable function.
+  "caseren()".
+
+  Language: ANSI C with POSIX extensions
+  Author: David Dunan Ross Palmer, Daybo Logic.
+  Copyright (C) 2005, Daybo Logic, all rights reserved.
+  http://www.daybologic.co.uk/
+*/
+
+#include <stdio.h>
+#include <stdio.h>
+#if defined(__BORLANDC__) && defined(HDRSTOP)
+# pragma hdrstop
+#endif
+
+#include "libcaseren.h"
+/*-------------------------------------------------------------------------*/
+static const char *const Stamp = "20050202"; /* YYYMMDD */
+
+static unsigned short int IllegalModeBits(
+  unsigned short int ModeBits
+);
+/*-------------------------------------------------------------------------*/
+enum caseren_Error caseren(
+  const char *PathName,
+  unsigned short int ModeBits
+)
+{
+  /* Check for illegal mode bits */
+  if ( IllegalModeBits(ModeBits) )
+    return crParam;
+
+  return crSuccess;
+}
+/*-------------------------------------------------------------------------*/
+static unsigned short int IllegalModeBits(
+  unsigned short int ModeBits
+)
+{
+  unsigned short int badbits = 0;
+  int mask = CASEREN_MODEBITS_RESERVED16; /* First reserved region */
+
+  while ( !(mask & CASEREN_MODEBITS_USERDEF64) ) { /* In reserved area */
+    if ( ModeBits & mask ) {
+      badbits++;
+      #ifndef NDEBUG
+        fprintf(
+          stderr,
+          "libcaseren: Reserved bit %d set in mask\n"
+          "ModeBits: %04X\n",
+          mask,
+          ModeBits
+        );
+      #endif /*!NDEBUG*/
+    }
+    mask <<= 1;
+  }
+
+  if ( !(ModeBits & CASEREN_MODEBITS_DIR) &&
+       !(ModeBits & CASEREN_MODEBITS_FILE) ) {
+    #ifndef NDEBUG
+    fprintf(
+      stderr,
+      "libcaseren: You must set either the DIR or FILE mode bit!\n"
+      "ModeBits: %X\n",
+      ModeBits
+    );
+    #endif /*!NDEBUG*/
+    badbits++;
+  }
+  return badbits;
+}
+/*-------------------------------------------------------------------------*/
+unsigned int caseren_Ver(
+  unsigned int *PMinor,
+  unsigned int *PPatch
+)
+{
+  if ( PMinor ) *PMinor = CASEREN_VER_MINOR;
+  if ( PPatch ) *PPatch = CASEREN_VER_PATCH;
+  return CASEREN_VER_MAJOR;
+}
+/*-------------------------------------------------------------------------*/
+const char *const caseren_VerBuildDate()
+{
+  static const char *const bdate = __DATE__;
+  return bdate;
+}
+/*-------------------------------------------------------------------------*/
+const char *const caseren_VerBuildTime()
+{
+  static const char *const btime = __TIME__;
+  return btime;
+}
+/*-------------------------------------------------------------------------*/
+const char *const caseren_VerStamp()
+{
+  return Stamp;
+}
+/*-------------------------------------------------------------------------*/
+/*
+  This is the user-header for the mini-library libcaseren.
+  It is used by the "caseren" command-line utility and by
+  other programs which wish to incorporate this functionality.
+
+  Language: ANSI C with POSIX extensions
+  Author: David Dunan Ross Palmer, Daybo Logic.
+  Copyright (C) 2005, Daybo Logic, all rights reserved.
+  http://www.daybologic.co.uk/
+*/
+
+#ifndef INC_LIBCASEREN_H
+#define INC_LIBCASEREN_H
+/*-------------------------------------------------------------------------*/
+/*
+  These are the possible error returns from caseren()
+*/
+enum caseren_Error {
+  crSuccess = 0, /* Success */
+  crGeneral,     /* General failure */
+  crDepthLimit,  /* Directory depth limit reached */
+  crParam,       /* Illegal parameters, nothing was done */
+  crNotFound     /* PathName was not found */
+};
+
+/*
+  These macros set the ModeBits.
+*/
+#define CASEREN_MODEBITS_ZERO (0) /* This doesn't do anything but default */
+#define CASEREN_MODEBITS_RECURSE (1) /* Recurse into sub-directories */
+#define CASEREN_MODEBITS_UC (2) /* Uppercase (default is lowercase) */
+/* One or both of the following bits _must_ be set */
+#define CASEREN_MODEBITS_DIR (4) /* Change case of directory names */
+#define CASEREN_MODEBITS_FILE (8) /* Change case of file names */
+/* All these bits are reserved and must not be set */
+#define CASEREN_MODEBITS_RESERVED16 (16)
+#define CASEREN_MODEBITS_RESERVED32 (32)
+/*
+  Two more bits are explicitly user-defined.  They do nothing
+  in the distributed library and are ignored.
+*/
+#define CASEREN_MODEBITS_USERDEF64 (64)
+#define CASEREN_MODEBITS_USERDEF128 (128)
+/* All other bits do not officially exist */
+
+enum caseren_Error caseren(
+  const char *PathName,
+  unsigned short int ModeBits
+);
+
+#define CASEREN_VER_MAJOR (0)
+#define CASEREN_VER_MINOR (1)
+#define CASEREN_VER_PATCH (0)
+/*
+  These functions return version information about the library
+  portion of caseren.  caseren_Ver() returns an unsigned integer
+  which is the major version number of the library.  The minor number
+  and patch level are passed back via pointers.  they are optional.
+  You should display the version number as Major.Minor.Patch
+*/
+unsigned int caseren_Ver(
+  unsigned int *PMinor,
+  unsigned int *PPatch
+);
+
+/*
+  These functions return a pointer to the date at which the library was
+  built and the time the function was built respectively.  This is in
+  human-readable format.  Generated by __DATE__ and __TIME__.
+*/
+const char *const caseren_VerBuildDate(void);
+const char *const caseren_VerBuildTime(void);
+
+/*
+  This function returns a string in the form YYYYMMDD, to represent
+  the year, month and day the library was built.
+*/
+const char *const caseren_VerStamp(void);
+/*-------------------------------------------------------------------------*/
+#endif /*!INC_LIBCASEREN_H*/