mklist: Unzip source.

This commit is contained in:
Laurens Valk 2020-09-19 23:38:13 +02:00
parent 1e7408e4b1
commit 6d266bb980
No known key found for this signature in database
GPG Key ID: C5FCCBB5E9FB117A
8 changed files with 716 additions and 0 deletions

Binary file not shown.

9
mklist/include/alloc.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef ALLOC_H
#define ALLOC_H
#define farmalloc(n) malloc((n))
#define farrealloc(i,j) realloc((i),(j))
#define farcoreleft() (0)
#endif /* ALLOC_H */

23
mklist/include/conio.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef CONIO_H
#define CONIO_H
#define getch() getc(stdin)
int stricmp(const char *str1, const char *str2)
{
const unsigned char * ptr1 = (unsigned char *) str1;
const unsigned char * ptr2 = (unsigned char *) str2;
unsigned char c1, c2;
while ((c1 = toupper(*ptr1++)) == (c2 = toupper(*ptr2++)))
{
if (!c1)
{
return(0); // end of both strings reached, so they match
}
}
// first non-matching char was reached, including possibly 0 on one or the other string
return(c1 - c2);
}
#endif /* CONIO_H */

72
mklist/include/dir.h Normal file
View File

@ -0,0 +1,72 @@
#ifndef DIR_H
#define DIR_H
# include <dirent.h>
# include <sys/stat.h>
# include <unistd.h>
struct ffblk
{
char *ff_name;
};
#if defined(MAC)
char separator = ':';
# define SEPSTR ":"
#else
char separator = '/';
# define SEPSTR "/"
#endif
DIR *dirp;
struct dirent *dir;
char directory[300];
int findnext(struct ffblk *ffb)
{
struct stat statbuf;
char filename[300];
for (dir = readdir(dirp); dir; dir = readdir(dirp))
{
ffb->ff_name = dir->d_name;
strcpy(filename, directory);
strcat(filename, SEPSTR);
strcat(filename, dir->d_name);
stat(filename,&statbuf);
if ((statbuf.st_mode & S_IFDIR) == 0) // Skip directories
return 0; // not done
}
return 1; // done
}
int findfirst(char *path, struct ffblk *ffb, int first)
{
int i;
char *ptr;
/* Localize Directory Separators */
for(i=0; i<strlen(path); i++)
{
if ((path[i] == '/') || (path[i] == '\\'))
{
path[i] = separator;
}
else
path[i] = tolower(path[i]);
}
strcpy(directory,path);
/* Remove any trailing separators (and anything after them) */
if ( (ptr = strrchr(directory, separator)) )
*ptr = 0;
dirp = opendir(directory);
if (!dirp)
return 1; // done
return findnext(ffb);
}
#endif /* DIR_H */

16
mklist/makefile Normal file
View File

@ -0,0 +1,16 @@
CC=gcc
CFLAGS= -I./include
AR = ar
RANLIB = ranlib
SRCS = mklist.c
OBJS = $(SRCS:.c=.o)
all : mklist
mklist : $(OBJS)
$(CC) $(CFLAGS) -o mklist $(OBJS)

596
mklist/mklist.c Normal file
View File

@ -0,0 +1,596 @@
/*
* mklist.c, a replacement for James Jessiman's makelist
* Copyright (C) 1999 Lars C. Hassing
*
* 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 program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*****************************************************************************
Please do not edit this file. In stead contact Lars C. Hassing (lch@cci.dk)
to get your changes integrated in a future release.
******************************************************************************/
/*
990214 lch Release v1.0
990316 lch Release v1.1: added options + minor changes to sort algorithms
990518 lch Release v1.2: Skip "~Moved to xxx" by default
20000703 lch Release v1.3: Added -i and -o
20030625 dmh Release v1.4: Ported to gcc.
200????? ??? Release v1.5: ??? Lost track of this one...
20090928 dmh Release v1.6beta1: Added -f -q -v -8 and allow 25 chars in filenames.
20100706 dmh Release v1.6: Added -l and made long format the default.
*/
/* Compile with Borland Turbo C 2.0: tcc -mc -d -f -k- -N -v- -y- -wrvl -wstv
-wucp -wnod -wpro -wuse -wsig -ncmdsrel -M src\mklist.c */
#include "stdio.h"
#include "stdlib.h"
#include "ctype.h"
#include "string.h"
#include "alloc.h"
#include "dir.h"
#include "conio.h"
char *ProgVer = "mklist v1.6 20100706 (C) 1999-2010 Lars C. Hassing lch@ccieurope.com";
int forceit = 0;
int quiet = 0;
/*****************************************************************/
/* Filename length compatibility stuff */
/*****************************************************************/
#ifndef _MAX_PATH
#define _MAX_PATH 256
#endif
char shortfilepath[MAX_PATH];
char shortfilename[MAX_PATH];
#ifdef __BORLANDC__
#define LACKS_BASENAME 1
int numlines = 1000; /* Use small chunks for DOS */
int namelen = 12; /* Set to 12 for 8.3 DOS compatibility. */
#else
#ifdef __TURBOC__
#define LACKS_BASENAME 1
int numlines = 1000; /* Use small chunks for DOS */
int namelen = 12; /* Set to 12 for 8.3 DOS compatibility. */
#else
int numlines = 16384; /* Allocate lines in bigger chunks if not DOS. */
int namelen = 25; /* LSC specs allow 25 chars in filename. */
#endif
#endif
#ifdef _WIN32
#include <windows.h>
#define LACKS_BASENAME 1
#else
int GetShortPathName(char *longpath, char * shortpath, int psize)
{
strncpy(shortpath, longpath, psize);
return(strlen(shortpath);
}
#endif
#if LACKS_BASENAME
char *basename( const char *filepath )
{
char *tmpstr, *ptr;
if (filepath == NULL)
{
return NULL;
}
if ( (ptr = strrchr(filepath, '\\')) || (ptr = strrchr(filepath, '/')) )
{
/* If there isn't anything after the last separator, the result is a 0-length string */
tmpstr = strdup(ptr+1);
}
else
{
/* dup the string, so caller can safely free whatever we return */
tmpstr = strdup(filepath);
}
return tmpstr;
}
#endif
/*****************************************************************/
int CmpNumber(const void *p1, const void *p2)
{
char *s1 = *((char **) p1);
char *s2 = *((char **) p2);
long l1;
long l2;
if (isdigit(*s1) && isdigit(*s2))
{
l1 = atol(s1);
l2 = atol(s2);
if (l1 != l2)
return (l1 < l2 ? -1 : 1);
/* Numbers are equal. Be sure to make 3005.dat come before 3005-1.dat */
do
{
l1 = (unsigned char) *s1++;
if ('A' <= l1 && l1 <= 'Z')
l1 -= ('A' - 'a');
else if (l1 == '.')
l1 = '\0'; /* Sort dot very first */
l2 = (unsigned char) *s2++;
if ('A' <= l2 && l2 <= 'Z')
l2 -= ('A' - 'a');
else if (l2 == '.')
l2 = '\0'; /* Sort dot very first */
} while (l1 && (l1 == l2));
return ((int) (l1 - l2));
}
return (stricmp(s1, s2));
}
/*****************************************************************/
int CmpDescription(const void *p1, const void *p2)
{
char *s1 = *((char **) p1);
char *s2 = *((char **) p2);
int Res;
#if 0
Res = stricmp(s1 + (namelen+2), s2 + (namelen+2));
#else
s1 += strcspn(s1, " \t"); /* Find the beginning of whitespace. */
s1 += strspn(s1, " \t"); /* Skip to end of whitespace (start of description). */
s2 += strcspn(s2, " \t"); /* Find the beginning of whitespace. */
s2 += strspn(s2, " \t"); /* Skip to end of whitespace (start of description). */
Res = stricmp(s1, s2);
#endif
return (Res ? Res : CmpNumber(p1, p2));
}
/*****************************************************************/
void PressAnyKey(void)
{
if (forceit)
return;
if (quiet)
return;
printf(" Press any key to continue");
getch();
printf("\n");
}
/*****************************************************************/
void PrintUsage(void)
{
printf("Options:\n");
printf(" -h You already figured this one out :-)\n");
printf(" -n Sort by Number\n");
printf(" -d Sort by Description\n");
printf(" -c Check for duplicate descriptions. \"parts.lst\" unchanged.\n");
printf(" -m Don't skip parts with \"~Moved to xxx\" description\n");
printf(" -~ Skip parts with ~ description, e.g. \"~Winch 2 x 4 x 2 Top\"\n");
printf(" -i <dir> input directory, default is \"PARTS\" in current directory\n");
printf(" -o <file> output filename, default is \"parts.lst\" in current directory\n");
printf(" -f Force it to finish. No prompts.\n");
printf(" -q Quiet mode. No warnings, and no prompts.\n");
printf(" -8 Use 8.3 names for compatibility.\n");
printf(" -t Truncating descriptions to fit in an 80 char terminal window.\n");
printf(" -r Ragged filename column. Size it to fit short filenames.\n");
printf(" -l Truncate Long descriptions at 64 chars.\n");
printf(" -v Print verbose info. Useful for debugging.\n");
}
/*****************************************************************/
int main(int argc, char **argv)
{
int CheckDuplicateDescriptions;
int SortBy;
int SkipTilde;
int SkipMovedto;
char *arg;
int c;
int i;
int j;
FILE *fp;
struct ffblk ffb;
int done;
int Len;
char **Lines;
int maxLines;
int nLines;
int pathlen;
char Line[200];
char Dirname[MAX_PATH];
char Filename[MAX_PATH];
char OutFilename[MAX_PATH];
char *s;
char *Description;
char *FormattedLine;
unsigned long farcoreleftStart;
unsigned long farcoreleftEnd;
long FileSize;
struct stat statbuf;
int verbose;
int ragged;
int terminalsized;
int longDescriptions;
printf("%s\n", ProgVer);
printf("Replacement for James Jessiman's makelist\n");
printf("Call with -h to see a list of options.\n\n");
strcpy(Dirname, "PARTS"); /* Default input directory path */
strcpy(OutFilename, "parts.lst"); /* Default output filename */
verbose = 0;
ragged = 0; /* Steve wanted it ragged (1) by default */
terminalsized = 0; /* Steve wanted it (1) to fit in 80 chars by default */
longDescriptions = 1; /* Do not truncate descriptions at 64 chars by default */
CheckDuplicateDescriptions = 0;
SortBy = 0;
SkipTilde = 0;
SkipMovedto = 1;
while (--argc > 0)
{
arg = *++argv;
if (arg[0] == '-')
{
switch (arg[1])
{
case '?':
case 'h':
PrintUsage();
exit(1);
break;
case '8':
namelen = 12;
break;
case 'c':
CheckDuplicateDescriptions = 1;
break;
case 'n':
case 'd':
SortBy = arg[1];
break;
case 'm':
SkipMovedto = 0;
break;
case '~':
SkipTilde = 1;
break;
case 'i':
if (--argc > 0)
strcpy(Dirname, *++argv);
else
{
PrintUsage();
printf("*** input directory expected as next argument after -i.\n");
exit(1);
}
break;
case 'o':
if (--argc > 0)
strcpy(OutFilename, *++argv);
else
{
PrintUsage();
printf("*** output filename expected as next argument after -o.\n");
exit(1);
}
break;
case 'q':
quiet = 1;
case 'f':
forceit = 1;
break;
case 'r':
ragged = ragged ^ 1;
break;
case 't':
terminalsized = terminalsized ^ 1;
break;
case 'l':
longDescriptions = longDescriptions ^ 1;
break;
case 'v':
verbose = 1;
break;
default:
PrintUsage();
printf("*** Unknown option '%s'.\n", arg);
exit(1);
break;
}
}
else
{
PrintUsage();
exit(1);
}
}
/* Do a stat to see if Dirname exists and is a directory. */
if (stat(Dirname, &statbuf) < 0)
{
printf("*** Could not stat input directory \"%s\".\n", Dirname);
exit(1);
}
if ((statbuf.st_mode & S_IFDIR) == 0)
{
printf("*** Input directory \"%s\" is not a directory.\n", Dirname);
exit(1);
}
if (CheckDuplicateDescriptions)
SortBy = 'd';
if (!SortBy)
{
if (forceit)
SortBy = 'd';
if (!quiet)
printf("Sorting by [D]escription.\n");
}
if (!SortBy)
{
printf("Sort by [N]umber or [D]escription: ");
c = getch();
printf("%c\n", c);
if (c == 'N' || c == 'n')
SortBy = 'n';
else if (c == 'D' || c == 'd')
SortBy = 'd';
else
{
printf("Nothing done.\n");
exit(0);
}
}
farcoreleftStart = farcoreleft();
nLines = 0;
maxLines = numlines;
Lines = farmalloc(maxLines * sizeof(char *));
if (!Lines)
{
printf("Out of memory after %d parts\n", nLines);
printf("Memory available at beginning: %ld kBytes\n",
(farcoreleftStart + 1023) / 1024);
exit(1);
}
strcpy(Filename, Dirname);
strcat(Filename, "\\");
pathlen = strlen(Filename);
strcat(Filename, "*.*");
for (done = findfirst(Filename, &ffb, 0); !done; done = findnext(&ffb))
{
if (verbose)
{
printf("Processing file: \"%s\"\n", ffb.ff_name);
}
strcpy(Filename + pathlen, ffb.ff_name);
fp = fopen(Filename, "rt");
if (!fp)
{
if (!quiet) printf("Cannot open \"%s\"", ffb.ff_name);
PressAnyKey();
continue;
}
fgets(Line, sizeof(Line), fp);
fclose(fp);
s = Line + strlen(Line) - 1;
while (s >= Line && (*s == '\n' || *s == '\r' || *s == '\t' || *s == ' '))
*s-- = '\0'; /* clear newline and trailing tabs
and spaces */
s = Line;
while (*s == '\t' || *s == ' ')
*s++;
if (*s++ != '0')
{
if (!quiet) printf("Line type 0 expected in \"%s\", skipping...", ffb.ff_name);
PressAnyKey();
continue;
}
while (*s == '\t' || *s == ' ')
*s++;
Description = s;
if (SkipTilde && Description[0] == '~')
continue;
if (SkipMovedto && strncmp(Description, "~Moved to", 9) == 0)
continue;
Len = strlen(Description);
if (Len == 0)
{
if (!quiet) printf("Empty description in \"%s\"", ffb.ff_name);
PressAnyKey();
}
if ((Len > 64) && !longDescriptions)
{
/* Original makelist truncates to 64 characters. */
if (!quiet)
{
printf("Description in \"%s\" will be truncated to 64 characters:\n",
ffb.ff_name);
printf("Before: \"%s\"\n", Description);
printf("After: \"%-64.64s\"\n", Description);
}
PressAnyKey();
}
if (namelen == 12)
FormattedLine = farmalloc(79);
else
FormattedLine = farmalloc(256);
if (!FormattedLine)
{
printf("Out of memory after %d parts\n", nLines);
printf("Memory available at beginning: %ld kBytes\n",
(farcoreleftStart + 1023) / 1024);
exit(1);
}
if (namelen > 12)
strcpy(shortfilename, ffb.ff_name);
else
{
GetShortPathName(Filename, shortfilepath, MAX_PATH);
s = basename(shortfilepath);
strcpy(shortfilename, s);
if (s != NULL)
free(s);
if (strcmp(ffb.ff_name, shortfilename))
{
if (!quiet)
printf("Filename \"%s\" will be shortened to %s\n",
ffb.ff_name, shortfilename);
PressAnyKey();
}
}
Len = strlen(shortfilename);
if (Len > namelen)
{
if (!quiet)
printf("Filename \"%s\" will be truncated to %d characters.\n",
shortfilename, namelen);
PressAnyKey();
}
shortfilename[namelen] = 0;
if (namelen == 12)
sprintf(FormattedLine, "%-12s %-64.64s", shortfilename, Description);
else if (ragged && terminalsized)
{
if (Len > 14) /* Squeeze every last char out of the 80. */
sprintf(FormattedLine, "%s %-64.64s", shortfilename, Description);
else
sprintf(FormattedLine, "%-14s %-64.64s", shortfilename, Description);
}
else if (ragged && longDescriptions)
{
if (Len > 12)
sprintf(FormattedLine, "%s %s", shortfilename, Description);
else
sprintf(FormattedLine, "%-12s %s", shortfilename, Description);
}
else if (ragged)
{
if (Len > 12)
sprintf(FormattedLine, "%s %-64.64s", shortfilename, Description);
else
sprintf(FormattedLine, "%-12s %-64.64s", shortfilename, Description);
}
else if (longDescriptions)
sprintf(FormattedLine, "%-25s %s", shortfilename, Description);
else
sprintf(FormattedLine, "%-25s %s", shortfilename, Description);
if (terminalsized)
{
if (namelen == 12)
FormattedLine[78] = 0;
else
FormattedLine[80] = 0;
}
if (verbose)
{
printf("%d:\t%s\n", nLines, FormattedLine);
}
if (nLines >= maxLines)
{
/* Let's have another 1000 pointers */
maxLines += numlines;
Lines = farrealloc(Lines, maxLines * sizeof(char *));
if (!Lines)
{
printf("Out of memory after %d parts\n", nLines);
printf("Memory available at beginning: %ld kBytes\n",
(farcoreleftStart + 1023) / 1024);
exit(1);
}
}
Lines[nLines++] = FormattedLine;
if (nLines % 100 == 0)
printf("%d parts so far...\r", nLines);
}
printf("%d parts found in %s.\n", nLines, Dirname);
if (nLines == 0)
{
printf("No parts found, nothing done.\n");
exit(0);
}
printf("Sorting...\n");
qsort(Lines, nLines, sizeof(Lines[0]),
(SortBy == 'n') ? CmpNumber : CmpDescription);
if (CheckDuplicateDescriptions)
{
printf("Checking for duplicate descriptions. \"%s\" unchanged.\n", OutFilename);
for (i = 0; i < nLines; i += j)
{
for (j = 1; i + j < nLines; j++)
{
if (stricmp(Lines[i] + (namelen+2), Lines[i + j] + (namelen+2)) != 0)
break; /* OK to break, lines are sorted */
if (j == 1) /* First duplicate */
printf("%s\n", Lines[i]);
printf("%s\n", Lines[i + j]);
}
if (j > 1) /* Duplicates found */
PressAnyKey();
}
}
else
{
fp = fopen(OutFilename, "wt");
if (!fp)
{
printf("Cannot open \"%s\" for writing.\n", OutFilename);
exit(1);
}
for (i = 0; i < nLines; i++)
fprintf(fp, "%s\n", Lines[i]);
FileSize = ftell(fp);
fclose(fp);
printf("\"%s\" successfully written, %ld kBytes\n", OutFilename,
(FileSize + 1023) / 1024);
}
if (numlines > 1000) /* if not Borland DOS compiler then skip the mem msg. */
{
return (0);
}
farcoreleftEnd = farcoreleft();
printf("Maximum memory usage: %ld kBytes of %ld kBytes available\n",
(farcoreleftStart - farcoreleftEnd + 1023) / 1024,
(farcoreleftStart + 1023) / 1024);
return (0);
}

Binary file not shown.

Binary file not shown.