#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAXLINES 5000
char *lineptr[MAXLINES];
int realines(char *lineptr[], int max);
void writelines(char *lineptr[], int nlins);
void my_qsort(char *lineptr[], int left, int right, int (*cmp)(const char *, const char *));
int numcmp(const char to[], const char from[]);
int strcmp_ignore_case(const char str1[], const char str2[]);
int reverse(const char str1[], const char str2[]);
int mystcmp(const char to[], const char from[]);
int (*compare)(const char str1[], const char str2[]);
int (*strcmp_base)(const char to[], const char from[]);
int isdirectory(char input);
int directory_order_bool;
int
main(int argc, char *argv[])
{
char flag;
int numeric = 0, reverse_bool = 0, ignore_case_bool = 0;
int nlins;
while (--argc > 0 && **++argv == '-')
while ((flag = *++*argv))
switch (flag) {
case 'n' :
numeric = 1;
break;
case 'r' :
reverse_bool = 1;
break;
case 'f' :
ignore_case_bool = 1;
break;
case 'd' :
directory_order_bool = 1;
break;
default :
printf("Err: illigial option %c\n", flag);
}
if (argc)
printf("Usage: sort -nrf\n");
else if ((nlins = realines(lineptr, MAXLINES)) > 0) {
strcmp_base = ignore_case_bool ? strcmp_ignore_case : mystcmp;
compare = numeric ? numcmp : strcmp_base;
my_qsort(lineptr, 0, nlins - 1, reverse_bool ? reverse : compare);
writelines(lineptr, nlins);
}
return 0;
}
void swap(char *lineptr[], int to, int from);
void
my_qsort(char *lineptr[], int left, int right, int (*cmp)(const char *, const char *))
{
int last, i;
if (left >= right)
return;
swap(lineptr, left, (left+right)/2);
last = left;
for (i = left+1; i <= right; i++) {
if ((*cmp)(lineptr[i], lineptr[left]) < 0)
swap(lineptr, ++last, i);
}
swap(lineptr, left, last);
my_qsort(lineptr, left, last-1, cmp);
my_qsort(lineptr, last+1, right, cmp);
}
int
numcmp(const char to[], const char from[])
{
double n1 = atof(to);
double n2 = atof(from);
if (n1 < n2)
return -1;
else if (n1 > n2)
return 1;
else
return 0;
}
void
swap(char *lineptr[], int to, int from)
{
char *temp;
temp = lineptr[to];
lineptr[to] = lineptr[from];
lineptr[from] = temp;
}
void
writelines(char *lineptr[], int nlins)
{
while (nlins--)
printf("%s", *lineptr++);
}
#define MAXLEN 1000
int sneed_getine(char str[], int max);
int
realines(char *lineptr[], int max)
{
int len, nlins;
char buff[MAXLEN], *temp;
for (nlins = 0; (len = sneed_getine(buff, MAXLEN)) > 0; nlins++) {
if (nlins < max && (temp = malloc(len+1)) != NULL) {
strcpy(temp, buff);
lineptr[nlins] = temp;
}
else
return -1;
}
return nlins;
}
int
sneed_getine(char str[], int max)
{
char input;
char *str_og = str;
while ( --max && (input = getchar()) != EOF && input != '\n')
*str++ = input;
if (max && input == '\n')
*str++ = input;
*str = '\0';
return str - str_og;
}
int
reverse(const char str1[], const char str2[])
{
return (*compare)(str2, str1);
}
int
strcmp_ignore_case(const char to[], const char from[])
{
if (directory_order_bool) {
for (; *to && *from; to++, from++)
if (isdirectory(tolower(*from)) && tolower(*from) != tolower(*to))
break;
}
else
for (; *to && *from && tolower(*to) == tolower(*from); to++, from++)
;
return tolower(*to) - tolower(*from);
}
int
isdirectory(char input)
{
if (isalpha(input) || isdigit(input) || isblank(input))
return 1;
else
return 0;
}
int
mystcmp(const char to[], const char from[])
{
if (directory_order_bool) {
for (; *to && *from; to++, from++)
if (isdirectory(*from) && *from != *to)
break;
}
else
for (; *to && *from && *to == *from; to++, from++)
;
return *to - *from;
}