Delete the toolchain builddir after building the toolchain.
[AROS.git] / workbench / c / Sort.c
blob2e9c8c2f113ec175d436f28983f11f9343cdace6
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Sorts the contents of a file
6 Lang: English
7 */
8 /*****************************************************************************
10 NAME
12 Sort
14 SYNOPSIS
16 FROM/A,TO/A,COLSTART/K,CASE/S,NUMERIC/S
18 LOCATION
22 FUNCTION
24 Sorts the contents of a text file
26 INPUTS
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
34 RESULT
36 EXAMPLE
38 BUGS
40 SEE ALSO
42 INTERNALS
44 HISTORY
46 ******************************************************************************/
48 #include <clib/macros.h>
49 #include <exec/memory.h>
50 #include <exec/types.h>
51 #include <dos/dos.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>
60 #define DEBUG 0
61 #include <aros/debug.h>
63 #include <string.h>
65 #define TEMPLATE "FROM/A,TO/A,COLSTART/K,CASE/S,NUMERIC/S"
67 #define ARG_FROM 0
68 #define ARG_TO 1
69 #define ARG_COLSTART 2
70 #define ARG_CASE 3
71 #define ARG_NUMERIC 4
73 #define ARG_NUM 5
75 const TEXT version[] = "$VER: Sort 41.1 (7.9.1999)";
77 struct sorted_data
79 struct sorted_data * next;
80 UBYTE * data;
81 ULONG len; // length of line including '\n'.
84 struct Locale * locale;
86 int compare(struct sorted_data * sd1,
87 struct sorted_data * sd2,
88 ULONG col,
89 BOOL case_on)
91 ULONG len = MIN(sd1->len, sd2->len);
93 /* FIXME: It seems like StrnCmp of locale does not work. */
94 #if 1
95 LONG retval = 0;
97 if (TRUE == case_on)
99 int i = col;
101 while (i < len)
103 BOOL a,b;
104 a = IsUpper(locale,(ULONG)*(sd1->data+col+i));
105 b = IsUpper(locale,(ULONG)*(sd2->data+col+i));
107 if (a == b)
109 if (0 != (retval = StrnCmp(locale,
110 sd1->data+col,
111 sd2->data+col,
113 SC_COLLATE2)));
114 break;
116 else
118 retval = b - a;
119 break;
122 i++;
125 else
128 retval=StrnCmp(locale,
129 sd1->data+col,
130 sd2->data+col,
131 len,
132 SC_COLLATE2);
134 if (0 == retval)
136 if (sd1->len < sd2->len)
137 retval = -100;
138 else
139 retval = +100;
143 return retval;
145 #else
146 int i = col;
147 char * str1 = sd1->data;
148 char * str2 = sd2->data;
150 while (i < len)
152 if (str1[i] != str2[i])
153 return (int)(str1[i] - str2[i]);
155 i++;
158 return (int)sd1->len - (int)sd2->len;
159 #endif
163 struct sorted_data * sort(UBYTE * data,
164 ULONG data_len,
165 STRPTR colstart,
166 BOOL case_on,
167 BOOL is_numeric)
169 ULONG pos = 0;
170 ULONG col = 0;
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;
176 if (colstart)
178 while (*colstart >= '0' && *colstart <= '9')
179 col = col * 10 + *colstart++ - '0';
180 if (col > 0)
181 col-=1;
184 while (pos < data_len)
186 ULONG begin = pos;
187 ULONG len;
189 while (pos < data_len && data[pos] != 0x0a)
190 pos++;
192 if (data[pos] == 0x0a || pos == data_len)
193 len = pos++ - begin;
194 else
195 len = ++pos - begin;
197 cur = AllocMem(sizeof(struct sorted_data), MEMF_ANY|MEMF_CLEAR);
199 if (cur)
201 cur->data = data + begin;
202 cur->len = len;
204 if (len > col)
207 ** Insert it into the list of sorted lines
209 if (NULL != first)
212 ** To be first in the list?
214 if (compare(cur, first, col, case_on) < 0)
216 cur->next = first;
217 first = cur;
219 else
221 struct sorted_data * _cur = first;
223 while (1)
226 ** Insert it after the current one and before the
227 ** next one?
229 if (NULL == _cur->next)
231 _cur->next = cur;
232 break;
234 if (compare(cur, _cur->next, col, case_on) < 0)
236 cur -> next = _cur->next;
237 _cur-> next = cur;
238 break;
241 _cur = _cur->next;
244 } /* if (NULL != first) */
245 else
246 first = cur;
248 else
250 /* this line is too short to sort it in */
251 if (NULL == tooshort)
253 tooshort = cur;
254 tooshort_last = cur;
256 else
258 tooshort_last->next = cur;
259 tooshort_last = cur;
262 } /* if (cur) */
266 if (NULL != tooshort)
268 tooshort_last->next = first;
269 first = tooshort;
272 return first;
276 ULONG write_data(struct sorted_data * start, BPTR file_out)
278 BOOL write = TRUE;
279 ULONG error = 0;
281 while (start)
283 struct sorted_data * next = start->next;
285 if (TRUE == write)
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);
292 if (-1 == error)
293 write = FALSE;
295 FreeMem(start, sizeof(struct sorted_data));
296 start = next;
299 if (FALSE == write)
300 return error;
302 return 0;
305 int __nocommandline;
307 int main (void)
309 IPTR args[ARG_NUM] = { (IPTR) NULL, (IPTR) NULL, (IPTR) NULL, FALSE, FALSE};
310 struct RDArgs *rda;
311 ULONG error = 0;
313 locale = OpenLocale(NULL);
314 if (!locale)
316 PutStr("Could not open locale!\n");
317 return -1;
320 rda = ReadArgs(TEMPLATE, args, NULL);
321 if (rda)
323 BPTR lock_in;
324 lock_in = Lock((STRPTR)args[ARG_FROM], ACCESS_READ);
326 if (lock_in)
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)
333 UBYTE * data = NULL;
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);
342 if (data)
344 BPTR in;
345 if ((in = OpenFromLock(lock_in))) {
346 ULONG read = Read(in, data, fib->fib_Size);
348 if (-1 != read)
350 struct sorted_data * sd;
351 sd = sort(data,
352 fib->fib_Size,
353 (STRPTR)args[ARG_COLSTART],
354 (BOOL)args[ARG_CASE],
355 (BOOL)args[ARG_NUMERIC]);
357 error = write_data(sd, file_out);
359 Close(in);
360 lock_in = BNULL;
362 FreeVec(data);
363 }/* if (data) */
365 Close(file_out);
366 } /* if (file_out) */
367 FreeDosObject(DOS_FIB, fib);
368 if (lock_in)
369 UnLock(lock_in);
370 } /* if (lock_in) */
371 FreeArgs(rda);
373 else
374 error=RETURN_FAIL;
376 if (error)
377 PrintFault(IoErr(), "Sort");
379 return error;