home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
pitools
/
c2pi.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-03-22
|
14KB
|
705 lines
/* This quick hack can be used to generate Product-Info files from a typical
"Contents" file. It creates subdirectories in the current directory,
one for each "Product" found in the Contents file (and with the same name),
and generates a Product-Info file within that directory.
This code is Public Domain. -Fred Fish
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
char buffer[4096];
char *bufp;
int buflen;
char shortdesc[256];
char productname[256];
char filename[256];
FILE *fout;
int
read_new_entry ()
{
int thisch;
int usech;
int prevch;
int prevprevch;
prevch = '\000';
thisch = '\000';
bufp = buffer;
*bufp = '\000';
/* Discard all leading whitespace */
do
{
thisch = getchar ();
if (thisch == EOF)
{
return (0);
}
}
while (isspace (thisch));
ungetc (thisch, stdin);
/* Collect everything up to the next pair of double newlines or EOF into
the buffer, compressing out extra whitespace and converting newlines
into whitespace. */
for (;;)
{
prevprevch = prevch;
prevch = thisch;
thisch = getchar ();
if (thisch == EOF)
{
ungetc (thisch, stdin);
break;
}
else if (thisch == '\n' && (prevch == '\n'))
{
break;
}
else if (thisch == '\n')
{
usech = ' ';
}
else if (thisch == '\t')
{
usech = ' ';
}
else
{
usech = thisch;
}
if (isspace (usech) && isspace (prevch) && (prevprevch != '.'))
{
/* Compress out repeated whitespace except for two spaces following
a previous end of a sentance. */
continue;
}
if (isspace (usech) && (prevch == '-'))
{
/* Eat occurances of "- " that are generated by hyphenated lines. */
bufp--;
continue;
}
*bufp++ = usech;
}
*bufp = '\000';
return (1);
}
void
remove_it (start, end)
char *start;
char *end;
{
if (*start == ',')
{
/* The clause we are removing starts in the middle of a sentance. */
if ((*end == '.') || (*end == '\000'))
{
/* The clause is the last one of the sentance, so build end of
sentance and set up to start shuffling with next sentance. */
*start++ = '.';
*start++ = ' ';
*start++ = ' ';
if (*end != '\000')
{
end++;
}
while (isspace (*end))
{
end++;
}
}
else if (*end == ',')
{
/* The clause is entirely within the middle of the sentance,
so just shuffle it away. */
}
else if (*end == ' ')
{
/* The clause we are removing is only the leading part of a clause of
the sentance, so keep the ',' that separates it from the previous
part of the sentance. */
start++;
}
else
{
fprintf (stderr, "%s: problem shuffling out '", productname);
while (start < end)
{
fputc (*start++, stderr);
}
fputc ('\'', stderr);
fputc ('\n', stderr);
return;
}
}
else if ((*start == ' ') && isupper (*(start + 1)))
{
/* The clause we are removing starts a sentance, so skip over the
leading blank and position to start shuffling into the place where
the old sentance started. */
start++;
if ((*end == '.') || (*end == '\000'))
{
/* The clause is a complete sentance, position to start shuffle
with next sentance. */
if (*end != '\000')
{
end++;
}
while (isspace (*end))
{
end++;
}
}
else if ((*end == ',') || (*end == ' '))
{
/* The clause starts a sentance, so position to start with
next clause, and capitalize it. This is true even if it
is only a portion of the starting clause (the word following
the portion becomes capitalized). */
end++;
while (isspace (*end))
{
end++;
}
*end = toupper (*end);
}
else
{
fprintf (stderr, "%s: problem shuffling out '", productname);
while (start < end)
{
fputc (*start++, stderr);
}
fputc ('\'', stderr);
fputc ('\n', stderr);
return;
}
}
/* Shuffle all the characters down to fill the hole and null terminate
the result. */
while (*end != '\000')
{
*start++ = *end++;
}
*start = '\000';
}
/* Try to pick off the author information from the end of the description.
Account for multiple authors separated by ',' characters, and strip
out any '.' characters, which are occasionally found at the end.
Separate the author info from the end of the description by writing
a null byte into it's first character. */
void
extract_author ()
{
char *foundit;
char *scan;
int length;
int neednewline;
foundit = strstr (bufp, "Author:");
length = 7;
if (foundit == NULL)
{
foundit = strstr (bufp, "Authors:");
length = 8;
}
if (foundit != NULL)
{
fprintf (fout, ".author\n");
scan = foundit;
scan += length;
while (isspace (*scan))
{
scan++;
}
neednewline = FALSE;
while (*scan != '\000')
{
neednewline = TRUE;
if ((strncmp (scan, "amiga port by ", 14) == 0) ||
(strncmp (scan, "Amiga port by ", 14) == 0))
{
scan += 14;
}
if ((strncmp (scan, "ported to amiga by ", 19) == 0))
{
scan += 19;
}
if (*scan == '.')
{
/* eat it */
scan++;
}
else if (*scan == ',')
{
fputc ('\n', fout);
scan++;
while (isspace (*scan))
{
scan++;
}
}
else
{
fputc (*scan, fout);
scan++;
}
}
if (neednewline)
{
fputc ('\n', fout);
}
remove_it (foundit, scan);
}
}
/* Try to extract version information, and remove it from the buffer in
the process. */
void
extract_current_version ()
{
char *foundit;
char *scan;
int length;
char ver[256];
char *verp;
foundit = strstr (bufp, " Version ");
length = 9;
if (foundit == NULL)
{
foundit = strstr (bufp, " This is version ");
length = 17;
}
if (foundit == NULL)
{
foundit = strstr (bufp, ", version ");
length = 10;
}
if (foundit != NULL)
{
fprintf (fout, ".version\n");
scan = foundit + length;
while (isspace (*scan))
{
scan++;
}
verp = ver;
while ((*scan != '\000') && (*scan != ',') &&
(!((*scan == '.') && (*(scan + 1) == ' '))))
{
*verp++ = *scan++;
}
if ((verp - ver) > 16)
{
fprintf (fout, "?.?\n");
return;
}
*verp = '\000';
fprintf (fout, "%s\n", ver);
strcat (shortdesc, ", V");
strcat (shortdesc, ver);
remove_it (foundit, scan);
}
}
/* Try to extract previous version information, and remove it from the buffer in
the process. */
void
extract_update_to ()
{
char *foundit;
char *scan;
int length;
char *verp;
char *refp;
char ver[256];
char ref[256];
foundit = strstr (bufp, " An update to version ");
length = 22;
if (foundit == NULL)
{
foundit = strstr (bufp, ", an update to version ");
length = 23;
}
if (foundit != NULL)
{
scan = foundit + length;
while (isspace (*scan))
{
scan++;
}
/* Suck out the old version number */
verp = ver;
while (!isspace (*scan) && (*scan != ','))
{
*verp++ = *scan++;
}
*verp = '\000';
/* look for " on disk " */
if (strncmp (scan, " on disk ", 9) == 0)
{
scan += 9;
/* look for "number " */
if (strncmp (scan, "number ", 7) == 0)
{
scan += 7;
}
/* look for '#' */
if (*scan == '#')
{
scan++;
}
/* Suck out the old disk number */
refp = ref;
while ((*scan != '.') && (*scan != ','))
{
*refp++ = *scan++;
}
*refp = '\000';
if ((atoi (ref) <= 0) || (atoi (ref) > 999) || (strlen (ref) > 3))
{
fprintf (stderr, "%s: '%s' is not a disk number\n",
productname, ref);
}
else
{
fprintf (fout, ".reference\n");
fprintf (fout, "AmigaLibDisk%d:%s/\n", atoi (ref), productname);
fprintf (fout, "%s\n", ver);
remove_it (foundit, scan);
}
}
}
}
/* Try to extract source information, and remove it from the buffer in
the process. */
void
extract_source_information ()
{
char *foundit;
char *scan;
int length;
char src[256];
char *srcp;
char *descp;
foundit = strstr (bufp, " Includes source");
length = 16;
if (foundit == NULL)
{
foundit = strstr (bufp, ", includes source");
length = 17;
}
if (foundit != NULL)
{
fprintf (fout, ".source\n");
scan = foundit + length;
strcpy (src, "Includes source");
if (strncmp (scan, " in ", 4) != 0)
{
/* Generally when a Contents file says "Includes source.", without
specifying the source, it is implied that the source is in C. */
strcat (src, " in C");
srcp = src + strlen (src);
descp = "C";
}
else
{
strcat (src, " in ");
scan += 4;
srcp = src + strlen (src);
descp = srcp;
while (isspace (*scan))
{
scan++;
}
while ((*scan != '\000') && (*scan != ',') && (*scan != '.'))
{
*srcp++ = *scan++;
}
}
*srcp = '\000';
strcat (shortdesc, ", ");
strcat (shortdesc, descp);
strcat (shortdesc, " source");
*srcp++ = '.';
*srcp = '\000';
fprintf (fout, "%s\n", src);
remove_it (foundit, scan);
}
}
/* Try to remove "Binary only." */
void
remove_binary_only ()
{
char *foundit;
char *scan;
int length;
foundit = strstr (bufp, " Binary only");
length = 12;
if (foundit == NULL)
{
foundit = strstr (bufp, ", binary only");
length = 13;
}
if (foundit != NULL)
{
scan = foundit + length;
remove_it (foundit, scan);
}
}
/* Try to find and remove "Shareware" */
void
extract_shareware ()
{
char *foundit;
char *scan;
int length;
foundit = strstr (bufp, " Shareware");
length = 10;
if (foundit == NULL)
{
foundit = strstr (bufp, ", shareware");
length = 11;
}
if (foundit != NULL)
{
fprintf (fout, ".distribution\nShareware\n");
scan = foundit + length;
strcat (shortdesc, ", shareware");
remove_it (foundit, scan);
}
}
/* Try to find and remove "Public Domain" */
void
extract_public_domain ()
{
char *foundit;
char *scan;
int length;
foundit = strstr (bufp, " Public domain");
length = 14;
if (foundit == NULL)
{
foundit = strstr (bufp, ", public domain");
length = 15;
}
if (foundit != NULL)
{
fprintf (fout, ".distribution\nPublic Domain\n");
scan = foundit + length;
remove_it (foundit, scan);
strcat (shortdesc, ", PD");
}
}
/* Try to find and remove "freeware" */
void
extract_freeware ()
{
char *foundit;
char *scan;
int length;
foundit = strstr (bufp, " Freeware");
length = 9;
if (foundit == NULL)
{
foundit = strstr (bufp, ", freeware");
length = 10;
}
if (foundit != NULL)
{
fprintf (fout, ".distribution\nFreeware\n");
scan = foundit + length;
strcat (shortdesc, ", freeware");
remove_it (foundit, scan);
}
}
/* Output lines of description text, limiting each line to 75 characters. */
void
write_description ()
{
char *descp;
fprintf (fout, ".description\n");
while (*bufp != '\000')
{
while (isspace (*bufp))
{
bufp++;
}
descp = bufp;
if (strlen (bufp) > 75)
{
bufp += 75;
while ((bufp > descp) && (!isspace (*bufp)))
{
bufp--;
}
while ((bufp > descp) && (isspace (*bufp)))
{
bufp--;
}
bufp++;
*bufp++ = '\000';
}
else
{
while (*bufp != '\000')
{
bufp++;
}
}
if (*descp != '\000')
{
fprintf (fout, "%s\n", descp);
}
}
}
void
write_described_by ()
{
fprintf (fout, ".described-by\n");
fprintf (fout, "Automatically generated from Contents file by c2pi program.\n");
}
void
write_short ()
{
fprintf (fout, ".short\n");
shortdesc[40] = '\000';
fprintf (fout, "%s\n", shortdesc);
}
void
write_product_info ()
{
char *namep;
/* Ignore Contents file header "This is disk ..." */
if (strncmp (buffer, "This is disk", 12) == 0)
{
return;
}
/* Ignore Contents file headers "========..." */
if (strncmp (buffer, "==========", 10) == 0)
{
return;
}
/* Pick off the first word as the product name */
bufp = buffer;
namep = productname;
while (!isspace (*bufp))
{
*namep++ = *bufp++;
}
*namep = '\000';
/* Make a directory by that name and create a Product-Info file
within it. */
mkdir (productname, 0775);
sprintf (filename, "%s/Product-Info", productname);
if ((fout = fopen (filename, "w")) == NULL)
{
perror (filename);
return;
}
fprintf (fout, ".name\n%s\n", productname);
sprintf (shortdesc, "%s", productname);
/* Skip leading whitespace on description. */
while (isspace (*bufp))
{
bufp++;
}
buflen = strlen (bufp);
for (;;)
{
extract_author ();
extract_current_version ();
extract_update_to ();
extract_source_information ();
remove_binary_only ();
extract_shareware ();
extract_public_domain ();
extract_freeware ();
if (strlen (bufp) == buflen)
{
break; /* No change this iteration */
}
else
{
buflen = strlen (bufp);
}
}
write_description ();
write_described_by ();
write_short ();
}
main ()
{
while (read_new_entry ())
{
write_product_info ();
}
}