1 /* Copyright (c) 2000, 2021, Oracle and/or its affiliates.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23
24 /*
25 things to define before including the file:
26
27 #define LS_LIST_ITEM ListItem
28 #define LS_COMPARE_FUNC_DECL compare_func var_name,
29 #define LS_COMPARE_FUNC_CALL(list_el1, list_el2) (*var_name)(list_el1, list_el2)
30 #define LS_NEXT(A) (A)->next
31 #define LS_SET_NEXT(A,val) (A)->next= val
32 #define LS_P_NEXT(A) &(A)->next
33 #define LS_NAME plistsort
34 #define LS_SCOPE static
35 #define LS_STRUCT_NAME ls_struct_name
36 */
37
38 typedef struct LS_STRUCT_NAME
39 {
40 LS_LIST_ITEM *list1;
41 int list_len;
42 int return_point;
43 } LS_STRUCT_NAME;
44
LS_NAME(LS_COMPARE_FUNC_DECL LS_LIST_ITEM * list,int list_len)45 LS_SCOPE LS_LIST_ITEM* LS_NAME(LS_COMPARE_FUNC_DECL LS_LIST_ITEM *list, int list_len)
46 {
47 LS_LIST_ITEM *list_end;
48 LS_LIST_ITEM *sorted_list;
49
50 struct LS_STRUCT_NAME stack[63], *sp= stack;
51
52 if (list_len < 2)
53 return list;
54
55 sp->list_len= list_len;
56 sp->return_point= 2;
57
58 recursion_point:
59
60 if (sp->list_len < 4)
61 {
62 LS_LIST_ITEM *e1, *e2;
63 sorted_list= list;
64 e1= LS_NEXT(sorted_list);
65 list_end= LS_NEXT(e1);
66 if (LS_COMPARE_FUNC_CALL(sorted_list, e1))
67 {
68 sorted_list= e1;
69 e1= list;
70 }
71 if (sp->list_len == 2)
72 {
73 LS_SET_NEXT(sorted_list, e1);
74 LS_SET_NEXT(e1, NULL);
75 goto exit_point;
76 }
77 e2= list_end;
78 list_end= LS_NEXT(e2);
79 if (LS_COMPARE_FUNC_CALL(e1, e2))
80 {
81 {
82 LS_LIST_ITEM *tmp_e= e1;
83 e1= e2;
84 e2= tmp_e;
85 }
86 if (LS_COMPARE_FUNC_CALL(sorted_list, e1))
87 {
88 LS_LIST_ITEM *tmp_e= sorted_list;
89 sorted_list= e1;
90 e1= tmp_e;
91 }
92 }
93
94 LS_SET_NEXT(sorted_list, e1);
95 LS_SET_NEXT(e1, e2);
96 LS_SET_NEXT(e2, NULL);
97 goto exit_point;
98 }
99
100 {
101 struct LS_STRUCT_NAME *sp0= sp++;
102 sp->list_len= sp0->list_len >> 1;
103 sp0->list_len-= sp->list_len;
104 sp->return_point= 0;
105 }
106 goto recursion_point;
107 return_point0:
108 sp->list1= sorted_list;
109 {
110 struct LS_STRUCT_NAME *sp0= sp++;
111 list= list_end;
112 sp->list_len= sp0->list_len;
113 sp->return_point= 1;
114 }
115 goto recursion_point;
116 return_point1:
117 {
118 LS_LIST_ITEM **hook= &sorted_list;
119 LS_LIST_ITEM *list1= sp->list1;
120 LS_LIST_ITEM *list2= sorted_list;
121
122 if (LS_COMPARE_FUNC_CALL(list1, list2))
123 {
124 LS_LIST_ITEM *tmp_e= list2;
125 list2= list1;
126 list1= tmp_e;
127 }
128 for (;;)
129 {
130 *hook= list1;
131 do
132 {
133 if (!(list1= *(hook= LS_P_NEXT(list1))))
134 {
135 *hook= list2;
136 goto exit_point;
137 }
138 } while (LS_COMPARE_FUNC_CALL(list2, list1));
139
140 *hook= list2;
141 do
142 {
143 if (!(list2= *(hook= LS_P_NEXT(list2))))
144 {
145 *hook= list1;
146 goto exit_point;
147 }
148 } while (LS_COMPARE_FUNC_CALL(list1, list2));
149 }
150 }
151
152 exit_point:
153 switch ((sp--)->return_point)
154 {
155 case 0: goto return_point0;
156 case 1: goto return_point1;
157 default:;
158 }
159
160 return sorted_list;
161 }
162
163
164 #undef LS_LIST_ITEM
165 #undef LS_NEXT
166 #undef LS_SET_NEXT
167 #undef LS_P_NEXT
168 #undef LS_NAME
169 #undef LS_STRUCT_NAME
170 #undef LS_SCOPE
171 #undef LS_COMPARE_FUNC_DECL
172 #undef LS_COMPARE_FUNC_CALL
173
174