DtSvc/DtUtil1: fix implicit function declarations
[oweals/cde.git] / cde / lib / DtSvc / DtUtil1 / DtsSort.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*
24  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
25  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
26  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
27  * (c) Copyright 1993, 1994 Novell, Inc.                                *
28  */
29 /*
30  *+SNOTICE
31  *
32  *      $XConsortium: DtsSort.c /main/6 1996/11/21 19:56:08 drk $
33  *
34  *      RESTRICTED CONFIDENTIAL INFORMATION:
35  *      
36  *      The information in this document is subject to special
37  *      restrictions in a confidential disclosure agreement bertween
38  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
39  *      document outside HP, IBM, Sun, USL, SCO, or Univel wihtout
40  *      Sun's specific written approval.  This documment and all copies
41  *      and derivative works thereof must be returned or destroyed at
42  *      Sun's request.
43  *
44  *      Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
45  *
46  *+ENOTICE
47  */
48 #include <stdlib.h>
49 #include <ctype.h>
50 #include <string.h>
51 #include <sys/mman.h>
52 #include <fcntl.h>
53 #include <sys/stat.h>
54 #define X_INCLUDE_STRING_H
55 #define XOS_USE_XT_LOCKING
56 #include <X11/Xos_r.h>
57 #include <Dt/DbReader.h>
58 #include "Dt/DtsDb.h"
59 #include "Dt/Dts.h"
60
61 #if !defined(__linux__)
62 extern  char    *strdup(const char *);
63 #endif
64
65 static char *
66 get_value(DtDtsDbRecord *ce_entry, char *value)
67 {
68         int     i=0;
69         XrmQuark        tmp = XrmStringToQuark (value);
70
71         for(i = 0; i < ce_entry->fieldCount; i++)
72         {
73                 if(ce_entry->fieldList[i]->fieldName == tmp)
74                 {
75                         return(ce_entry->fieldList[i]->fieldValue);
76                 }
77         }
78         return(NULL);
79 }
80
81 void
82 parts_of_pattern(char *c, int *spec, int *count, int *front)
83 {
84         int     nested = 0;
85         int     found = 0;
86         int     len;
87
88         (*count) = 0;
89         (*spec) = 0;
90         (*front) = 0;
91
92         while(*c)
93         {
94                 if((len = mblen(c, MB_CUR_MAX)) > 1) {
95                     (*count) += len;
96                     if(!found)
97                         (*front) += len;
98                     c += len;
99                     continue;
100                 }
101                 switch(*c)
102                 {
103                 case    '*':
104                         if(!nested)
105                         {
106                                 (*spec) += 100;
107                                 found = 1;
108                         }
109                         break;
110                 case    '?':
111                         if(!nested)
112                         {
113                                 (*spec) += 1;
114                                 found = 1;
115                         }
116                         break;
117                 case    '[':
118                         (*spec) += 10;
119                         nested ++;
120                         found = 1;
121                         break;
122                 case    ']':
123                         if(nested)
124                         {
125                                 nested --;
126                         }
127                         break;
128                 case    '\\':
129                         if(!nested)
130                         {
131                             if((len = mblen(c + 1, MB_CUR_MAX)) > 1) {
132                                 (*count) += len + 1;
133                                 c += len;
134                             }
135                             else {
136                                 (*count) += 2;
137                                 c++;
138                             }
139                         }
140                         break;
141                 default:
142                         (*count)++;
143                         if(!found)
144                         {
145                                 (*front)++;
146                         }
147                 }
148                 c++;
149         }
150 }
151
152 int
153 check_pattern(char *value1, char *value2)
154 {
155         int             spec1 = 0,count1 = 0, front1 = 0;
156         int             spec2 = 0,count2 = 0, front2 = 0;
157
158         if(value1 && value2)
159         {
160                 parts_of_pattern(value1, &spec1, &count1, &front1);
161                 parts_of_pattern(value2, &spec2, &count2, &front2);
162         }
163         else if(!value1 && !value2)
164         {
165                 return(0);
166         }
167         else if(value1)
168         {
169                 return(-1);
170         }
171         else
172         {
173                 return(1);
174         }
175
176
177         if(front1 != front2)
178         {
179                 return(front2 - front1);
180         }
181
182         if(spec1 != spec2)
183         {
184                 return(spec1 - spec2);
185         }
186         if(count1 != count2)
187         {
188                 return(count2-count1);
189         }
190
191         return (0);
192 }
193
194 int
195 mode_count(char *c)
196 {
197         int     count = 0;
198
199         while(c && *c)
200         {
201
202                 if(strchr("fcbdlrwx", *c))
203                 {
204                         count++;
205                 }
206                 c++;
207         }
208         return(count);
209 }
210
211 #ifdef DEBUG
212 static int
213 bool(int i)
214 {
215         if(i > 0) return(1);
216         if(i < 0) return(-1);
217         else return(0);
218 }
219
220 #endif
221
222 static int check_content(char *val1, char *val2)
223 {
224         char    *v1 = strdup(val1);
225         char    *v2 = strdup(val2);
226         char    *loc1;
227         char    *loc2;
228         char    *type1;
229         char    *type2;
230         char    *cnt1;
231         char    *cnt2;
232         int     ret = 0;
233         _Xstrtokparams  strtok_buf;
234
235         loc1 = _XStrtok(v1, "\t \n", strtok_buf);
236         type1 = _XStrtok(NULL, "\t \n", strtok_buf);
237         cnt1 = &type1[strlen(type1)+1];
238         while(isspace((u_char)*cnt1))cnt1++;
239
240         loc2 = _XStrtok(v2, "\t \n", strtok_buf);
241         type2 = _XStrtok(NULL, "\t \n", strtok_buf);
242         cnt2 = &type2[strlen(type2)+1];
243         while(isspace((u_char)*cnt2))cnt2++;
244
245         ret = strcmp(type1, type2);
246         if(loc1 && loc2 && ret == 0)
247         {
248                 int     l1 = atoi(loc1);
249                 int     l2 = atoi(loc2);
250                 int     sl1 = strlen(cnt1);
251                 int     sl2 = strlen(cnt2);
252                 char    sym;
253
254                      if (sl1 > sl2) ret = -1;
255                 else if (sl1 < sl2) ret =  1;
256                 else if (l1  > l2 ) ret =  1;
257                 else if (l1  < l2 ) ret = -1;
258                 else ret = strcmp(cnt1,cnt2);
259
260 #ifdef DEBUG
261                 switch(bool(ret))
262                 {
263                 case    0:
264                         sym = '=';
265                         break;
266                 case    -1:
267                         sym = '>';
268                         break;
269                 case    1:
270                         sym = '<';
271                 }
272                 printf("cc (%d,%d) for \"%s\" %c \"%s\"\n", l1, l2, cnt1, sym, cnt2);
273 #endif
274         }
275         free(v1);
276         free(v2);
277         return(ret);
278 }
279
280 static int
281 sfe(DtDtsDbRecord * item1, DtDtsDbRecord * item2)
282 {
283         int             test1 = 0;
284         int             test2 = 0;
285         int             loc1;
286         int             loc2;
287         char           *value1, *value2;
288         DtDtsDbRecord  *rec;
289         DtDtsDbField   *fld;
290         int             val;
291
292         test1 |= get_value(item1, DtDTS_CONTENT) ? 2 : 0;
293         test2 |= get_value(item2, DtDTS_CONTENT) ? 2 : 0;
294
295         value1 = get_value(item1, DtDTS_NAME_PATTERN);
296         if (value1)
297         {
298                 if ((strlen(value1) == 1) && (*value1 == '*'))
299                 {
300                         test1 |= 0;
301                 }
302                 else
303                 {
304                         test1 |= 1;
305                 }
306         }
307
308         value2 = get_value(item2, DtDTS_NAME_PATTERN);
309         if (value2)
310         {
311                 if ((strlen(value2) == 1) && (*value2 == '*'))
312                 {
313                         test2 |= 0;
314                 }
315                 else
316                 {
317                         test2 |= 1;
318                 }
319         }
320
321         if (!(test1 & 1))
322         {
323                 test1 |= get_value(item1, DtDTS_PATH_PATTERN) ? 1 : 0;
324         }
325         if (!(test2 & 1))
326         {
327                 test2 |= get_value(item2, DtDTS_PATH_PATTERN) ? 1 : 0;
328         }
329
330         switch (test1)
331         {
332         case 0:
333                 loc1 = 4;
334                 break;
335         case 1:
336                 loc1 = 2;
337                 break;
338         case 2:
339                 loc1 = 3;
340                 break;
341         case 3:
342                 loc1 = 1;
343                 break;
344         }
345
346         switch (test2)
347         {
348         case 0:
349                 loc2 = 4;
350                 break;
351         case 1:
352                 loc2 = 2;
353                 break;
354         case 2:
355                 loc2 = 3;
356                 break;
357         case 3:
358                 loc2 = 1;
359                 break;
360         }
361
362         if (loc1 - loc2)
363         {
364                 return (loc1 - loc2);
365         }
366
367         if (loc1 == 2)          /* loc1 == loc2 */
368         {
369                 val = check_pattern(get_value(item1, DtDTS_PATH_PATTERN),
370                                         get_value(item2, DtDTS_PATH_PATTERN));
371                 if(val)
372                 {
373                         return(val);
374                 }
375                 val = check_pattern(get_value(item1, DtDTS_NAME_PATTERN),
376                                         get_value(item2, DtDTS_NAME_PATTERN));
377                 if(val)
378                 {
379                         return(val);
380                 }
381         }
382
383         if( loc1 == 3)
384         {
385                 val = check_content(get_value(item1, DtDTS_CONTENT),
386                                         get_value(item2, DtDTS_CONTENT));
387                 if(val)
388                 {
389                         return(val);
390                 }
391         }
392         /*
393          * neither pattern nor content, only needs to compare the
394          * number of fields. If they are equal then which has shorter
395          * record name will be more specific
396          */
397         if (item2->fieldCount - item1->fieldCount)
398         {
399                 return (item2->fieldCount - item1->fieldCount);
400         }
401
402         val =   mode_count(get_value(item2, DtDTS_MODE)) -
403                 mode_count(get_value(item1, DtDTS_MODE));
404         if(val)
405         {
406                 return(val);
407         }
408
409
410         val = strlen(XrmQuarkToString(item1->recordName)) - 
411               strlen(XrmQuarkToString(item2->recordName));
412         if(val)
413         {
414                 return(val);
415         }
416         else
417         {
418                 return(item1->recordName - item2->recordName);
419         }
420 }
421
422 int
423 cde_dc_compare(DtDtsDbRecord ** a, DtDtsDbRecord ** b)
424 {
425         DtDtsDbRecord **x = (DtDtsDbRecord **) a;
426         DtDtsDbRecord **y = (DtDtsDbRecord **) b;
427         int             results;
428         char            c;
429
430         results = sfe(*x, *y);
431         return(results);
432 }
433
434 static int
435 cde_ft_field_value(XrmQuark  name_quark)
436 {
437         if (name_quark == XrmStringToQuark(DtDTS_PATH_PATTERN))
438                 return (1);
439         else if (name_quark == XrmStringToQuark(DtDTS_NAME_PATTERN))
440                 return (2);
441         else if (name_quark == XrmStringToQuark(DtDTS_MODE))
442                 return (3);
443         else if (name_quark == XrmStringToQuark(DtDTS_LINK_PATH))
444                 return (4);
445         else if (name_quark == XrmStringToQuark(DtDTS_LINK_NAME))
446                 return (5);
447         else if (name_quark == XrmStringToQuark(DtDTS_CONTENT))
448                 return (6);
449         else if (name_quark == XrmStringToQuark(DtDTS_DATA_ATTRIBUTES_NAME))
450                 return (7);
451         else if (name_quark == XrmStringToQuark(DtDTS_DA_IS_SYNTHETIC))
452                 return (8);
453         else
454                 return (9);
455
456 }
457
458 int
459 cde_dc_field_compare(DtDtsDbField ** a, DtDtsDbField ** b)
460 {
461         return (cde_ft_field_value((*a)->fieldName) -
462                 cde_ft_field_value((*b)->fieldName));
463 }
464
465 int cde_da_compare(DtDtsDbRecord ** a, DtDtsDbRecord ** b)
466 {
467         int             results = ((*a)->recordName) - ((*b)->recordName);
468
469         if (!results)
470         {
471                 results = (*a)->seq - (*b)->seq;
472         }
473         return (results);
474 }