@@ -67,3 +67,213 @@ static int same_trailer(struct trailer_item *a, struct trailer_item *b)
67
67
{
68
68
return same_token (a , b ) && same_value (a , b );
69
69
}
70
+
71
+ static void free_trailer_item (struct trailer_item * item )
72
+ {
73
+ free (item -> conf .name );
74
+ free (item -> conf .key );
75
+ free (item -> conf .command );
76
+ free ((char * )item -> token );
77
+ free ((char * )item -> value );
78
+ free (item );
79
+ }
80
+
81
+ static void update_last (struct trailer_item * * last )
82
+ {
83
+ if (* last )
84
+ while ((* last )-> next != NULL )
85
+ * last = (* last )-> next ;
86
+ }
87
+
88
+ static void update_first (struct trailer_item * * first )
89
+ {
90
+ if (* first )
91
+ while ((* first )-> previous != NULL )
92
+ * first = (* first )-> previous ;
93
+ }
94
+
95
+ static void add_arg_to_input_list (struct trailer_item * on_tok ,
96
+ struct trailer_item * arg_tok ,
97
+ struct trailer_item * * first ,
98
+ struct trailer_item * * last )
99
+ {
100
+ if (after_or_end (arg_tok -> conf .where )) {
101
+ arg_tok -> next = on_tok -> next ;
102
+ on_tok -> next = arg_tok ;
103
+ arg_tok -> previous = on_tok ;
104
+ if (arg_tok -> next )
105
+ arg_tok -> next -> previous = arg_tok ;
106
+ update_last (last );
107
+ } else {
108
+ arg_tok -> previous = on_tok -> previous ;
109
+ on_tok -> previous = arg_tok ;
110
+ arg_tok -> next = on_tok ;
111
+ if (arg_tok -> previous )
112
+ arg_tok -> previous -> next = arg_tok ;
113
+ update_first (first );
114
+ }
115
+ }
116
+
117
+ static int check_if_different (struct trailer_item * in_tok ,
118
+ struct trailer_item * arg_tok ,
119
+ int check_all )
120
+ {
121
+ enum action_where where = arg_tok -> conf .where ;
122
+ do {
123
+ if (!in_tok )
124
+ return 1 ;
125
+ if (same_trailer (in_tok , arg_tok ))
126
+ return 0 ;
127
+ /*
128
+ * if we want to add a trailer after another one,
129
+ * we have to check those before this one
130
+ */
131
+ in_tok = after_or_end (where ) ? in_tok -> previous : in_tok -> next ;
132
+ } while (check_all );
133
+ return 1 ;
134
+ }
135
+
136
+ static void remove_from_list (struct trailer_item * item ,
137
+ struct trailer_item * * first ,
138
+ struct trailer_item * * last )
139
+ {
140
+ struct trailer_item * next = item -> next ;
141
+ struct trailer_item * previous = item -> previous ;
142
+
143
+ if (next ) {
144
+ item -> next -> previous = previous ;
145
+ item -> next = NULL ;
146
+ } else if (last )
147
+ * last = previous ;
148
+
149
+ if (previous ) {
150
+ item -> previous -> next = next ;
151
+ item -> previous = NULL ;
152
+ } else if (first )
153
+ * first = next ;
154
+ }
155
+
156
+ static struct trailer_item * remove_first (struct trailer_item * * first )
157
+ {
158
+ struct trailer_item * item = * first ;
159
+ * first = item -> next ;
160
+ if (item -> next ) {
161
+ item -> next -> previous = NULL ;
162
+ item -> next = NULL ;
163
+ }
164
+ return item ;
165
+ }
166
+
167
+ static void apply_arg_if_exists (struct trailer_item * in_tok ,
168
+ struct trailer_item * arg_tok ,
169
+ struct trailer_item * on_tok ,
170
+ struct trailer_item * * in_tok_first ,
171
+ struct trailer_item * * in_tok_last )
172
+ {
173
+ switch (arg_tok -> conf .if_exists ) {
174
+ case EXISTS_DO_NOTHING :
175
+ free_trailer_item (arg_tok );
176
+ break ;
177
+ case EXISTS_REPLACE :
178
+ add_arg_to_input_list (on_tok , arg_tok ,
179
+ in_tok_first , in_tok_last );
180
+ remove_from_list (in_tok , in_tok_first , in_tok_last );
181
+ free_trailer_item (in_tok );
182
+ break ;
183
+ case EXISTS_ADD :
184
+ add_arg_to_input_list (on_tok , arg_tok ,
185
+ in_tok_first , in_tok_last );
186
+ break ;
187
+ case EXISTS_ADD_IF_DIFFERENT :
188
+ if (check_if_different (in_tok , arg_tok , 1 ))
189
+ add_arg_to_input_list (on_tok , arg_tok ,
190
+ in_tok_first , in_tok_last );
191
+ else
192
+ free_trailer_item (arg_tok );
193
+ break ;
194
+ case EXISTS_ADD_IF_DIFFERENT_NEIGHBOR :
195
+ if (check_if_different (on_tok , arg_tok , 0 ))
196
+ add_arg_to_input_list (on_tok , arg_tok ,
197
+ in_tok_first , in_tok_last );
198
+ else
199
+ free_trailer_item (arg_tok );
200
+ break ;
201
+ }
202
+ }
203
+
204
+ static void apply_arg_if_missing (struct trailer_item * * in_tok_first ,
205
+ struct trailer_item * * in_tok_last ,
206
+ struct trailer_item * arg_tok )
207
+ {
208
+ struct trailer_item * * in_tok ;
209
+ enum action_where where ;
210
+
211
+ switch (arg_tok -> conf .if_missing ) {
212
+ case MISSING_DO_NOTHING :
213
+ free_trailer_item (arg_tok );
214
+ break ;
215
+ case MISSING_ADD :
216
+ where = arg_tok -> conf .where ;
217
+ in_tok = after_or_end (where ) ? in_tok_last : in_tok_first ;
218
+ if (* in_tok ) {
219
+ add_arg_to_input_list (* in_tok , arg_tok ,
220
+ in_tok_first , in_tok_last );
221
+ } else {
222
+ * in_tok_first = arg_tok ;
223
+ * in_tok_last = arg_tok ;
224
+ }
225
+ break ;
226
+ }
227
+ }
228
+
229
+ static int find_same_and_apply_arg (struct trailer_item * * in_tok_first ,
230
+ struct trailer_item * * in_tok_last ,
231
+ struct trailer_item * arg_tok )
232
+ {
233
+ struct trailer_item * in_tok ;
234
+ struct trailer_item * on_tok ;
235
+ struct trailer_item * following_tok ;
236
+
237
+ enum action_where where = arg_tok -> conf .where ;
238
+ int middle = (where == WHERE_AFTER ) || (where == WHERE_BEFORE );
239
+ int backwards = after_or_end (where );
240
+ struct trailer_item * start_tok = backwards ? * in_tok_last : * in_tok_first ;
241
+
242
+ for (in_tok = start_tok ; in_tok ; in_tok = following_tok ) {
243
+ following_tok = backwards ? in_tok -> previous : in_tok -> next ;
244
+ if (!same_token (in_tok , arg_tok ))
245
+ continue ;
246
+ on_tok = middle ? in_tok : start_tok ;
247
+ apply_arg_if_exists (in_tok , arg_tok , on_tok ,
248
+ in_tok_first , in_tok_last );
249
+ return 1 ;
250
+ }
251
+ return 0 ;
252
+ }
253
+
254
+ static void process_trailers_lists (struct trailer_item * * in_tok_first ,
255
+ struct trailer_item * * in_tok_last ,
256
+ struct trailer_item * * arg_tok_first )
257
+ {
258
+ struct trailer_item * arg_tok ;
259
+ struct trailer_item * next_arg ;
260
+
261
+ if (!* arg_tok_first )
262
+ return ;
263
+
264
+ for (arg_tok = * arg_tok_first ; arg_tok ; arg_tok = next_arg ) {
265
+ int applied = 0 ;
266
+
267
+ next_arg = arg_tok -> next ;
268
+ remove_from_list (arg_tok , arg_tok_first , NULL );
269
+
270
+ applied = find_same_and_apply_arg (in_tok_first ,
271
+ in_tok_last ,
272
+ arg_tok );
273
+
274
+ if (!applied )
275
+ apply_arg_if_missing (in_tok_first ,
276
+ in_tok_last ,
277
+ arg_tok );
278
+ }
279
+ }
0 commit comments