Files
typomix/typomix.c
2012-02-20 13:48:25 +01:00

238 lines
4.5 KiB
C
Raw Permalink Blame History

/*
* 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 */