2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
5 Desc: Sorts the contents of a file
8 /*****************************************************************************
16 FROM/A,TO/A,COLSTART/K,CASE/S,NUMERIC/S
24 Sorts the contents of a text file
28 FROM -- file to read from
29 TO -- file to output to
30 COLSTART -- column at which the comparison begins
31 CASE -- sort is case sensitive. Uppercase items are output first
32 NUMERIC -- lines are interpreted as numbers
46 ******************************************************************************/
48 #include <clib/macros.h>
49 #include <exec/memory.h>
50 #include <exec/types.h>
52 #include <dos/exall.h>
53 #include <proto/dos.h>
54 #include <proto/exec.h>
55 #include <proto/utility.h>
56 #include <proto/locale.h>
57 #include <libraries/locale.h>
58 #include <utility/tagitem.h>
61 #include <aros/debug.h>
65 #define TEMPLATE "FROM/A,TO/A,COLSTART/K,CASE/S,NUMERIC/S"
69 #define ARG_COLSTART 2
75 const TEXT version
[] = "$VER: Sort 41.1 (7.9.1999)";
79 struct sorted_data
* next
;
81 ULONG len
; // length of line including '\n'.
84 struct Locale
* locale
;
86 int compare(struct sorted_data
* sd1
,
87 struct sorted_data
* sd2
,
91 ULONG len
= MIN(sd1
->len
, sd2
->len
);
93 /* FIXME: It seems like StrnCmp of locale does not work. */
104 a
= IsUpper(locale
,(ULONG
)*(sd1
->data
+col
+i
));
105 b
= IsUpper(locale
,(ULONG
)*(sd2
->data
+col
+i
));
109 if (0 != (retval
= StrnCmp(locale
,
128 retval
=StrnCmp(locale
,
136 if (sd1
->len
< sd2
->len
)
147 char * str1
= sd1
->data
;
148 char * str2
= sd2
->data
;
152 if (str1
[i
] != str2
[i
])
153 return (int)(str1
[i
] - str2
[i
]);
158 return (int)sd1
->len
- (int)sd2
->len
;
163 struct sorted_data
* sort(UBYTE
* data
,
171 struct sorted_data
* first
= NULL
;
172 struct sorted_data
* cur
= NULL
;
173 struct sorted_data
* tooshort
= NULL
;
174 struct sorted_data
* tooshort_last
= NULL
;
178 while (*colstart
>= '0' && *colstart
<= '9')
179 col
= col
* 10 + *colstart
++ - '0';
184 while (pos
< data_len
)
189 while (pos
< data_len
&& data
[pos
] != 0x0a)
192 if (data
[pos
] == 0x0a || pos
== data_len
)
197 cur
= AllocMem(sizeof(struct sorted_data
), MEMF_ANY
|MEMF_CLEAR
);
201 cur
->data
= data
+ begin
;
207 ** Insert it into the list of sorted lines
212 ** To be first in the list?
214 if (compare(cur
, first
, col
, case_on
) < 0)
221 struct sorted_data
* _cur
= first
;
226 ** Insert it after the current one and before the
229 if (NULL
== _cur
->next
)
234 if (compare(cur
, _cur
->next
, col
, case_on
) < 0)
236 cur
-> next
= _cur
->next
;
244 } /* if (NULL != first) */
250 /* this line is too short to sort it in */
251 if (NULL
== tooshort
)
258 tooshort_last
->next
= cur
;
266 if (NULL
!= tooshort
)
268 tooshort_last
->next
= first
;
276 ULONG
write_data(struct sorted_data
* start
, BPTR file_out
)
283 struct sorted_data
* next
= start
->next
;
287 error
= Write(file_out
, start
->data
, start
->len
);
288 if (-1 != error
&& start
->data
[start
->len
-1] != 0x0a)
289 error
= Write(file_out
, "\n", 1);
295 FreeMem(start
, sizeof(struct sorted_data
));
309 IPTR args
[ARG_NUM
] = { (IPTR
) NULL
, (IPTR
) NULL
, (IPTR
) NULL
, FALSE
, FALSE
};
313 locale
= OpenLocale(NULL
);
316 PutStr("Could not open locale!\n");
320 rda
= ReadArgs(TEMPLATE
, args
, NULL
);
324 lock_in
= Lock((STRPTR
)args
[ARG_FROM
], ACCESS_READ
);
328 BPTR file_out
= Open((STRPTR
)args
[ARG_TO
], MODE_NEWFILE
);
329 struct FileInfoBlock
*fib
= AllocDosObject(DOS_FIB
, NULL
);
331 if (BNULL
!= file_out
&& fib
)
334 BOOL success
= Examine(lock_in
, fib
);
337 ** Read the input file into memory
339 if (fib
->fib_Size
&& success
)
340 data
= AllocVec(fib
->fib_Size
, MEMF_ANY
);
345 if ((in
= OpenFromLock(lock_in
))) {
346 ULONG read
= Read(in
, data
, fib
->fib_Size
);
350 struct sorted_data
* sd
;
353 (STRPTR
)args
[ARG_COLSTART
],
354 (BOOL
)args
[ARG_CASE
],
355 (BOOL
)args
[ARG_NUMERIC
]);
357 error
= write_data(sd
, file_out
);
366 } /* if (file_out) */
367 FreeDosObject(DOS_FIB
, fib
);
377 PrintFault(IoErr(), "Sort");