@@ -67,3 +67,213 @@ static int same_trailer(struct trailer_item *a, struct trailer_item *b)
6767{
6868 return same_token (a , b ) && same_value (a , b );
6969}
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