238 lines
4.5 KiB
C
238 lines
4.5 KiB
C
/*
|
||
* typomix.c
|
||
*
|
||
* Jens Kleineheismann <heinzel@heinzelwelt.de>
|
||
*/
|
||
|
||
/* include headers */
|
||
#include <ctype.h>
|
||
#include <libgen.h>
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <sysexits.h>
|
||
#include <time.h>
|
||
|
||
/* symbols */
|
||
#define TRUE 1
|
||
#define FALSE 0
|
||
#define VERSION "0.5"
|
||
|
||
/* prototypes */
|
||
int print_version(void);
|
||
int print_help(void);
|
||
char *scramble(char *word);
|
||
int xisalpha(char c);
|
||
|
||
/* definition of extern objects */
|
||
char *progname;
|
||
const char *version = VERSION;
|
||
|
||
/*
|
||
* main
|
||
*/
|
||
|
||
int main( int argc, char *argv[] ) {
|
||
int i;
|
||
int j;
|
||
char c;
|
||
char *p;
|
||
char *word;
|
||
FILE **input = NULL;
|
||
FILE **intemp = NULL;
|
||
size_t extend = 1024;
|
||
size_t maxlen;
|
||
|
||
/* Store program name without path */
|
||
if( (progname = strdup(basename(argv[0]))) == NULL ) {
|
||
fprintf(stderr, "%s: ", basename(argv[0]));
|
||
perror(NULL);
|
||
exit(EX_OSERR);
|
||
}
|
||
|
||
/* Initialize the random generator once here for scramble() */
|
||
srand( (unsigned int) time((time_t *)NULL) );
|
||
|
||
/* Initialize array of input streams */
|
||
if( (input = malloc(1 * sizeof(FILE*))) == NULL ) {
|
||
fprintf(stderr, "%s: ", progname);
|
||
perror(NULL);
|
||
exit(EX_OSERR);
|
||
}
|
||
input[0] = NULL;
|
||
|
||
/* Parse command line options */
|
||
for( i = 1 ; i < argc ; i++ ) {
|
||
if(!strncmp("--", argv[i], 2)) {
|
||
/* Current argument is a word option */
|
||
if(!strcmp( "--help", argv[i])) {
|
||
print_help();
|
||
exit(EX_OK);
|
||
} else if(!strcmp("--version", argv[i])) {
|
||
print_version();
|
||
exit(EX_OK);
|
||
} else {
|
||
fprintf(stderr, "%s: invalid option '%s'\n", progname, argv[i]);
|
||
fprintf(stderr, "Try '%s -h' for help.\n", progname);
|
||
exit(EX_USAGE);
|
||
}
|
||
} else if(!strncmp("-", argv[i], 1)) {
|
||
/* Current argument is one or more char options */
|
||
p = argv[i];
|
||
for( j = 1 ; (c = p[j]) != '\0' ; j++) {
|
||
switch(c) {
|
||
case 'h':
|
||
print_help();
|
||
exit(EX_OK);
|
||
break;
|
||
case 'V':
|
||
print_version();
|
||
exit(EX_OK);
|
||
break;
|
||
default:
|
||
fprintf(stderr, "%s: invalid option -- %c\n", progname, c);
|
||
fprintf(stderr, "Try '%s -h' for help.\n", progname);
|
||
exit(EX_USAGE);
|
||
}
|
||
}
|
||
} else {
|
||
/* Argument */
|
||
j = 0;
|
||
while(input[j++] != NULL);
|
||
|
||
intemp = input;
|
||
if( (input = malloc((j + 1) * sizeof(FILE*))) == NULL ) {
|
||
fprintf(stderr, "%s: ", progname);
|
||
perror(NULL);
|
||
exit(EX_OSERR);
|
||
}
|
||
j = 0;
|
||
while(intemp[j] != NULL) {
|
||
input[j] = intemp[j];
|
||
j++;
|
||
}
|
||
|
||
free(intemp);
|
||
|
||
if( (input[j++] = fopen(argv[i], "r")) == NULL ) {
|
||
fprintf(stderr, "%s: %s: ", progname, argv[i]);
|
||
perror(NULL);
|
||
}
|
||
|
||
input[j] = NULL;
|
||
}
|
||
}
|
||
|
||
if( input[0] == NULL ) {
|
||
if( (input = malloc(2 * sizeof(FILE*))) == NULL ) {
|
||
fprintf(stderr, "%s: ", progname);
|
||
perror(NULL);
|
||
exit(EX_OSERR);
|
||
}
|
||
|
||
input[0] = stdin;
|
||
input[1] = NULL;
|
||
}
|
||
|
||
for( i = 0 ; input[i] != NULL ; i++) {
|
||
word = p = NULL;
|
||
maxlen = j = 0;
|
||
while( (c = getc(input[i])) != EOF ) {
|
||
if(xisalpha(c)) {
|
||
if(j >= maxlen) {
|
||
p = word;
|
||
if( (word = malloc((maxlen + extend) )) == NULL ) {
|
||
fprintf(stderr, "%s: ", progname);
|
||
perror(NULL);
|
||
exit(EX_OSERR);
|
||
}
|
||
maxlen += extend;
|
||
if(p) {
|
||
strcpy(word, p);
|
||
free(p);
|
||
}
|
||
}
|
||
word[j++] = c;
|
||
} else if(word) {
|
||
|
||
word[j] = '\0';
|
||
scramble(word);
|
||
j = 0;
|
||
while(word[j] != '\0') {
|
||
putchar(word[j++]);
|
||
}
|
||
free(word);
|
||
word = NULL;
|
||
maxlen = 0;
|
||
j = 0;
|
||
putchar(c);
|
||
} else {
|
||
putchar(c);
|
||
}
|
||
}
|
||
}
|
||
exit(EX_OK);
|
||
}
|
||
|
||
int print_version( void ) {
|
||
printf("%s Version %s\n",progname, version);
|
||
return TRUE;
|
||
}
|
||
|
||
int print_help( void ) {
|
||
printf("\n");
|
||
printf("typomix scrambles letters within words.\n");
|
||
printf("\n");
|
||
printf("Usage: typomix [OPTIONS] [FILE]...\n");
|
||
printf("\n");
|
||
printf("If no file is given, input will be read from stdin.\n");
|
||
printf("\n");
|
||
printf("Options:\n");
|
||
printf(" -h, --help\n");
|
||
printf(" -V, --version\n");
|
||
printf("\n");
|
||
return TRUE;
|
||
}
|
||
|
||
char *scramble(char *word) {
|
||
int i;
|
||
int j;
|
||
char c;
|
||
size_t len;
|
||
|
||
len = strlen(word);
|
||
|
||
/* To short to scramble */
|
||
if( len < 4 )
|
||
return word;
|
||
|
||
|
||
for( i = j = 1 ; i < (len - 1) ; i++) {
|
||
j = 1 + (int)((float)(len - 2) * rand()/(RAND_MAX+1.0));
|
||
if( i != j ) {
|
||
c = word[i];
|
||
word[i] = word[j];
|
||
word[j] = c;
|
||
//fprintf(stderr, "%d <-> %d: %s\n", i, j, word);
|
||
}
|
||
}
|
||
return word;
|
||
}
|
||
|
||
int xisalpha(char c) {
|
||
switch(c) {
|
||
case '<EFBFBD>':
|
||
case '<EFBFBD>':
|
||
case '<EFBFBD>':
|
||
case '<EFBFBD>':
|
||
case '<EFBFBD>':
|
||
case '<EFBFBD>':
|
||
case '<EFBFBD>':
|
||
return 1;
|
||
}
|
||
|
||
return isalpha(c);
|
||
}
|
||
|
||
/* end */
|