Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Annotation of /trunk/src/tagging.c
Parent Directory
|
Revision Log
Revision 449 -
(hide annotations)
(download)
(as text)
Mon Jul 12 17:59:42 2010 UTC (14 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 15704 byte(s)
Mon Jul 12 17:59:42 2010 UTC (14 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 15704 byte(s)
Create a files.h header and put some of the most heavily used files.c functions into it and make them inline.
1 | amb | 393 | /*************************************** |
2 | amb | 449 | $Header: /home/amb/CVS/routino/src/tagging.c,v 1.3 2010-07-12 17:59:42 amb Exp $ |
3 | amb | 393 | |
4 | Load the tagging rules from a file and the functions for handling them. | ||
5 | |||
6 | Part of the Routino routing software. | ||
7 | ******************/ /****************** | ||
8 | This file Copyright 2010 Andrew M. Bishop | ||
9 | |||
10 | This program is free software: you can redistribute it and/or modify | ||
11 | it under the terms of the GNU Affero General Public License as published by | ||
12 | the Free Software Foundation, either version 3 of the License, or | ||
13 | (at your option) any later version. | ||
14 | |||
15 | This program is distributed in the hope that it will be useful, | ||
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | GNU Affero General Public License for more details. | ||
19 | |||
20 | You should have received a copy of the GNU Affero General Public License | ||
21 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
22 | ***************************************/ | ||
23 | |||
24 | |||
25 | #include <stdio.h> | ||
26 | #include <string.h> | ||
27 | #include <stdlib.h> | ||
28 | |||
29 | amb | 449 | #include "files.h" |
30 | amb | 393 | #include "tagging.h" |
31 | #include "xmlparse.h" | ||
32 | |||
33 | |||
34 | /* Global variables */ | ||
35 | |||
36 | TaggingRuleList NodeRules={NULL,0}; | ||
37 | TaggingRuleList WayRules={NULL,0}; | ||
38 | TaggingRuleList RelationRules={NULL,0}; | ||
39 | |||
40 | |||
41 | /* Local variables */ | ||
42 | |||
43 | TaggingRuleList *current_list=NULL; | ||
44 | TaggingRule *current_rule=NULL; | ||
45 | |||
46 | |||
47 | /* Local functions */ | ||
48 | |||
49 | static void apply_actions(TaggingRule *rule,int match,TagList *input,TagList *output); | ||
50 | |||
51 | |||
52 | /* The XML tag processing function prototypes */ | ||
53 | |||
54 | //static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding); | ||
55 | //static int RoutinoTaggingType_function(const char *_tag_,int _type_); | ||
56 | static int WayType_function(const char *_tag_,int _type_); | ||
57 | static int IfType_function(const char *_tag_,int _type_,const char *k,const char *v); | ||
58 | static int RelationType_function(const char *_tag_,int _type_); | ||
59 | static int OutputType_function(const char *_tag_,int _type_,const char *k,const char *v); | ||
60 | static int SetType_function(const char *_tag_,int _type_,const char *k,const char *v); | ||
61 | static int NodeType_function(const char *_tag_,int _type_); | ||
62 | |||
63 | |||
64 | /* The XML tag definitions */ | ||
65 | |||
66 | /*+ The NodeType type tag. +*/ | ||
67 | static xmltag NodeType_tag= | ||
68 | {"node", | ||
69 | 0, {NULL}, | ||
70 | NodeType_function, | ||
71 | {NULL}}; | ||
72 | |||
73 | /*+ The SetType type tag. +*/ | ||
74 | static xmltag SetType_tag= | ||
75 | {"set", | ||
76 | 2, {"k","v"}, | ||
77 | SetType_function, | ||
78 | {NULL}}; | ||
79 | |||
80 | /*+ The OutputType type tag. +*/ | ||
81 | static xmltag OutputType_tag= | ||
82 | {"output", | ||
83 | 2, {"k","v"}, | ||
84 | OutputType_function, | ||
85 | {NULL}}; | ||
86 | |||
87 | /*+ The RelationType type tag. +*/ | ||
88 | static xmltag RelationType_tag= | ||
89 | {"relation", | ||
90 | 0, {NULL}, | ||
91 | RelationType_function, | ||
92 | {NULL}}; | ||
93 | |||
94 | /*+ The IfType type tag. +*/ | ||
95 | static xmltag IfType_tag= | ||
96 | {"if", | ||
97 | 2, {"k","v"}, | ||
98 | IfType_function, | ||
99 | {&SetType_tag,&OutputType_tag,NULL}}; | ||
100 | |||
101 | /*+ The WayType type tag. +*/ | ||
102 | static xmltag WayType_tag= | ||
103 | {"way", | ||
104 | 0, {NULL}, | ||
105 | WayType_function, | ||
106 | {&IfType_tag,NULL}}; | ||
107 | |||
108 | /*+ The RoutinoTaggingType type tag. +*/ | ||
109 | static xmltag RoutinoTaggingType_tag= | ||
110 | {"routino-tagging", | ||
111 | 0, {NULL}, | ||
112 | NULL, | ||
113 | {&NodeType_tag,&WayType_tag,&RelationType_tag,NULL}}; | ||
114 | |||
115 | /*+ The xmlDeclaration type tag. +*/ | ||
116 | static xmltag xmlDeclaration_tag= | ||
117 | {"xml", | ||
118 | 2, {"version","encoding"}, | ||
119 | NULL, | ||
120 | {NULL}}; | ||
121 | |||
122 | |||
123 | /*+ The complete set of tags at the top level. +*/ | ||
124 | static xmltag *xml_toplevel_tags[]={&xmlDeclaration_tag,&RoutinoTaggingType_tag,NULL}; | ||
125 | |||
126 | |||
127 | /* The XML tag processing functions */ | ||
128 | |||
129 | |||
130 | /*++++++++++++++++++++++++++++++++++++++ | ||
131 | The function that is called when the NodeType XSD type is seen | ||
132 | |||
133 | int NodeType_function Returns 0 if no error occured or something else otherwise. | ||
134 | |||
135 | const char *_tag_ Set to the name of the element tag that triggered this function call. | ||
136 | |||
137 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. | ||
138 | ++++++++++++++++++++++++++++++++++++++*/ | ||
139 | |||
140 | static int NodeType_function(const char *_tag_,int _type_) | ||
141 | { | ||
142 | if(_type_&XMLPARSE_TAG_START) | ||
143 | current_list=&NodeRules; | ||
144 | |||
145 | return(0); | ||
146 | } | ||
147 | |||
148 | |||
149 | /*++++++++++++++++++++++++++++++++++++++ | ||
150 | The function that is called when the SetType XSD type is seen | ||
151 | |||
152 | int SetType_function Returns 0 if no error occured or something else otherwise. | ||
153 | |||
154 | const char *_tag_ Set to the name of the element tag that triggered this function call. | ||
155 | |||
156 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. | ||
157 | |||
158 | const char *k The contents of the 'k' attribute (or NULL if not defined). | ||
159 | |||
160 | const char *v The contents of the 'v' attribute (or NULL if not defined). | ||
161 | ++++++++++++++++++++++++++++++++++++++*/ | ||
162 | |||
163 | static int SetType_function(const char *_tag_,int _type_,const char *k,const char *v) | ||
164 | { | ||
165 | if(_type_&XMLPARSE_TAG_START) | ||
166 | AppendTaggingAction(current_rule,k,v,0); | ||
167 | |||
168 | return(0); | ||
169 | } | ||
170 | |||
171 | |||
172 | /*++++++++++++++++++++++++++++++++++++++ | ||
173 | The function that is called when the OutputType XSD type is seen | ||
174 | |||
175 | int OutputType_function Returns 0 if no error occured or something else otherwise. | ||
176 | |||
177 | const char *_tag_ Set to the name of the element tag that triggered this function call. | ||
178 | |||
179 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. | ||
180 | |||
181 | const char *k The contents of the 'k' attribute (or NULL if not defined). | ||
182 | |||
183 | const char *v The contents of the 'v' attribute (or NULL if not defined). | ||
184 | ++++++++++++++++++++++++++++++++++++++*/ | ||
185 | |||
186 | static int OutputType_function(const char *_tag_,int _type_,const char *k,const char *v) | ||
187 | { | ||
188 | if(_type_&XMLPARSE_TAG_START) | ||
189 | AppendTaggingAction(current_rule,k,v,1); | ||
190 | |||
191 | return(0); | ||
192 | } | ||
193 | |||
194 | |||
195 | /*++++++++++++++++++++++++++++++++++++++ | ||
196 | The function that is called when the RelationType XSD type is seen | ||
197 | |||
198 | int RelationType_function Returns 0 if no error occured or something else otherwise. | ||
199 | |||
200 | const char *_tag_ Set to the name of the element tag that triggered this function call. | ||
201 | |||
202 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. | ||
203 | ++++++++++++++++++++++++++++++++++++++*/ | ||
204 | |||
205 | static int RelationType_function(const char *_tag_,int _type_) | ||
206 | { | ||
207 | if(_type_&XMLPARSE_TAG_START) | ||
208 | current_list=&RelationRules; | ||
209 | |||
210 | return(0); | ||
211 | } | ||
212 | |||
213 | |||
214 | /*++++++++++++++++++++++++++++++++++++++ | ||
215 | The function that is called when the IfType XSD type is seen | ||
216 | |||
217 | int IfType_function Returns 0 if no error occured or something else otherwise. | ||
218 | |||
219 | const char *_tag_ Set to the name of the element tag that triggered this function call. | ||
220 | |||
221 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. | ||
222 | |||
223 | const char *k The contents of the 'k' attribute (or NULL if not defined). | ||
224 | |||
225 | const char *v The contents of the 'v' attribute (or NULL if not defined). | ||
226 | ++++++++++++++++++++++++++++++++++++++*/ | ||
227 | |||
228 | static int IfType_function(const char *_tag_,int _type_,const char *k,const char *v) | ||
229 | { | ||
230 | if(_type_&XMLPARSE_TAG_START) | ||
231 | { | ||
232 | current_rule=AppendTaggingRule(current_list,k,v); | ||
233 | } | ||
234 | |||
235 | return(0); | ||
236 | } | ||
237 | |||
238 | |||
239 | /*++++++++++++++++++++++++++++++++++++++ | ||
240 | The function that is called when the WayType XSD type is seen | ||
241 | |||
242 | int WayType_function Returns 0 if no error occured or something else otherwise. | ||
243 | |||
244 | const char *_tag_ Set to the name of the element tag that triggered this function call. | ||
245 | |||
246 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. | ||
247 | ++++++++++++++++++++++++++++++++++++++*/ | ||
248 | |||
249 | static int WayType_function(const char *_tag_,int _type_) | ||
250 | { | ||
251 | if(_type_&XMLPARSE_TAG_START) | ||
252 | current_list=&WayRules; | ||
253 | |||
254 | return(0); | ||
255 | } | ||
256 | |||
257 | |||
258 | /*++++++++++++++++++++++++++++++++++++++ | ||
259 | The function that is called when the RoutinoTaggingType XSD type is seen | ||
260 | |||
261 | int RoutinoTaggingType_function Returns 0 if no error occured or something else otherwise. | ||
262 | |||
263 | const char *_tag_ Set to the name of the element tag that triggered this function call. | ||
264 | |||
265 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. | ||
266 | ++++++++++++++++++++++++++++++++++++++*/ | ||
267 | |||
268 | //static int RoutinoTaggingType_function(const char *_tag_,int _type_) | ||
269 | //{ | ||
270 | // return(0); | ||
271 | //} | ||
272 | |||
273 | |||
274 | /*++++++++++++++++++++++++++++++++++++++ | ||
275 | The function that is called when the XML declaration is seen | ||
276 | |||
277 | int xmlDeclaration_function Returns 0 if no error occured or something else otherwise. | ||
278 | |||
279 | const char *_tag_ Set to the name of the element tag that triggered this function call. | ||
280 | |||
281 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. | ||
282 | |||
283 | const char *version The contents of the 'version' attribute (or NULL if not defined). | ||
284 | |||
285 | const char *encoding The contents of the 'encoding' attribute (or NULL if not defined). | ||
286 | ++++++++++++++++++++++++++++++++++++++*/ | ||
287 | |||
288 | //static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding) | ||
289 | //{ | ||
290 | // return(0); | ||
291 | //} | ||
292 | |||
293 | |||
294 | /*++++++++++++++++++++++++++++++++++++++ | ||
295 | The XML tagging rules parser. | ||
296 | |||
297 | int ParseXMLTaggingRules Returns 0 if OK or something else in case of an error. | ||
298 | |||
299 | const char *filename The name of the file to read. | ||
300 | ++++++++++++++++++++++++++++++++++++++*/ | ||
301 | |||
302 | int ParseXMLTaggingRules(const char *filename) | ||
303 | { | ||
304 | int retval; | ||
305 | |||
306 | if(!ExistsFile(filename)) | ||
307 | { | ||
308 | fprintf(stderr,"Error: Specified tagging rules file '%s' does not exist.\n",filename); | ||
309 | return(1); | ||
310 | } | ||
311 | |||
312 | FILE *file=fopen(filename,"r"); | ||
313 | |||
314 | if(!file) | ||
315 | { | ||
316 | fprintf(stderr,"Error: Cannot open tagging rules file '%s' for reading.\n",filename); | ||
317 | return(1); | ||
318 | } | ||
319 | |||
320 | retval=ParseXML(file,xml_toplevel_tags,XMLPARSE_UNKNOWN_ATTR_ERRNONAME); | ||
321 | |||
322 | fclose(file); | ||
323 | |||
324 | if(retval) | ||
325 | return(1); | ||
326 | |||
327 | return(0); | ||
328 | } | ||
329 | |||
330 | |||
331 | /*++++++++++++++++++++++++++++++++++++++ | ||
332 | Append a tagging rule to the list of rules. | ||
333 | |||
334 | TaggingRule *AppendTaggingRule Returns the latest rule (the just added one). | ||
335 | |||
336 | TaggingRuleList *rules The list of rules to add to. | ||
337 | |||
338 | const char *k The tag key. | ||
339 | |||
340 | const char *v The tag value. | ||
341 | ++++++++++++++++++++++++++++++++++++++*/ | ||
342 | |||
343 | TaggingRule *AppendTaggingRule(TaggingRuleList *rules,const char *k,const char *v) | ||
344 | { | ||
345 | if((rules->nrules%16)==0) | ||
346 | rules->rules=(TaggingRule*)realloc((void*)rules->rules,(rules->nrules+16)*sizeof(TaggingRule)); | ||
347 | |||
348 | rules->nrules++; | ||
349 | |||
350 | if(k) | ||
351 | rules->rules[rules->nrules-1].k=strcpy(malloc(strlen(k)+1),k); | ||
352 | else | ||
353 | rules->rules[rules->nrules-1].k=NULL; | ||
354 | |||
355 | if(v) | ||
356 | rules->rules[rules->nrules-1].v=strcpy(malloc(strlen(v)+1),v); | ||
357 | else | ||
358 | rules->rules[rules->nrules-1].v=NULL; | ||
359 | |||
360 | rules->rules[rules->nrules-1].nactions=0; | ||
361 | rules->rules[rules->nrules-1].actions=NULL; | ||
362 | |||
363 | return(&rules->rules[rules->nrules-1]); | ||
364 | } | ||
365 | |||
366 | |||
367 | /*++++++++++++++++++++++++++++++++++++++ | ||
368 | Append a tagging action to a tagging rule. | ||
369 | |||
370 | TaggingRule *rule The rule to add the action to. | ||
371 | |||
372 | const char *k The tag key. | ||
373 | |||
374 | const char *v The tag value. | ||
375 | |||
376 | int output Set to 1 if this is an output rule. | ||
377 | ++++++++++++++++++++++++++++++++++++++*/ | ||
378 | |||
379 | void AppendTaggingAction(TaggingRule *rule,const char *k,const char *v,int output) | ||
380 | { | ||
381 | if((rule->nactions%16)==0) | ||
382 | rule->actions=(TaggingAction*)realloc((void*)rule->actions,(rule->nactions+16)*sizeof(TaggingAction)); | ||
383 | |||
384 | rule->nactions++; | ||
385 | |||
386 | rule->actions[rule->nactions-1].output=output; | ||
387 | |||
388 | if(k) | ||
389 | rule->actions[rule->nactions-1].k=strcpy(malloc(strlen(k)+1),k); | ||
390 | else | ||
391 | rule->actions[rule->nactions-1].k=NULL; | ||
392 | |||
393 | if(v) | ||
394 | rule->actions[rule->nactions-1].v=strcpy(malloc(strlen(v)+1),v); | ||
395 | else | ||
396 | rule->actions[rule->nactions-1].v=NULL; | ||
397 | } | ||
398 | |||
399 | |||
400 | /*++++++++++++++++++++++++++++++++++++++ | ||
401 | amb | 401 | Create a new TagList structure. |
402 | |||
403 | TagList *NewTagList Returns the new allocated TagList. | ||
404 | ++++++++++++++++++++++++++++++++++++++*/ | ||
405 | |||
406 | TagList *NewTagList(void) | ||
407 | { | ||
408 | return((TagList*)calloc(sizeof(TagList),1)); | ||
409 | } | ||
410 | |||
411 | |||
412 | /*++++++++++++++++++++++++++++++++++++++ | ||
413 | amb | 393 | Append a tag to the list of tags. |
414 | |||
415 | TagList *tags The list of tags to add to. | ||
416 | |||
417 | const char *k The tag key. | ||
418 | |||
419 | const char *v The tag value. | ||
420 | ++++++++++++++++++++++++++++++++++++++*/ | ||
421 | |||
422 | void AppendTag(TagList *tags,const char *k,const char *v) | ||
423 | { | ||
424 | if((tags->ntags%16)==0) | ||
425 | { | ||
426 | amb | 401 | int i; |
427 | |||
428 | tags->k=(char**)realloc((void*)tags->k,(tags->ntags+16)*sizeof(char*)); | ||
429 | tags->v=(char**)realloc((void*)tags->v,(tags->ntags+16)*sizeof(char*)); | ||
430 | |||
431 | for(i=tags->ntags;i<(tags->ntags+16);i++) | ||
432 | tags->k[i]=tags->v[i]=NULL; | ||
433 | amb | 393 | } |
434 | |||
435 | amb | 401 | tags->k[tags->ntags]=strcpy(realloc(tags->k[tags->ntags],strlen(k)+1),k); |
436 | tags->v[tags->ntags]=strcpy(realloc(tags->v[tags->ntags],strlen(v)+1),v); | ||
437 | |||
438 | amb | 393 | tags->ntags++; |
439 | } | ||
440 | |||
441 | |||
442 | /*++++++++++++++++++++++++++++++++++++++ | ||
443 | Modify an existing tag or append a new tag to the list of tags. | ||
444 | |||
445 | TagList *tags The list of tags to modify. | ||
446 | |||
447 | const char *k The tag key. | ||
448 | |||
449 | const char *v The tag value. | ||
450 | ++++++++++++++++++++++++++++++++++++++*/ | ||
451 | |||
452 | void ModifyTag(TagList *tags,const char *k,const char *v) | ||
453 | { | ||
454 | int i; | ||
455 | |||
456 | for(i=0;i<tags->ntags;i++) | ||
457 | if(!strcmp(tags->k[i],k)) | ||
458 | { | ||
459 | amb | 401 | tags->v[i]=strcpy(realloc(tags->v[i],strlen(v)+1),v); |
460 | amb | 393 | return; |
461 | } | ||
462 | |||
463 | AppendTag(tags,k,v); | ||
464 | } | ||
465 | |||
466 | |||
467 | /*++++++++++++++++++++++++++++++++++++++ | ||
468 | Delete a tag list and the contents. | ||
469 | |||
470 | TagList *tags The list of tags to delete. | ||
471 | ++++++++++++++++++++++++++++++++++++++*/ | ||
472 | |||
473 | void DeleteTagList(TagList *tags) | ||
474 | { | ||
475 | int i; | ||
476 | |||
477 | for(i=0;i<tags->ntags;i++) | ||
478 | { | ||
479 | if(tags->k[i]) free(tags->k[i]); | ||
480 | if(tags->v[i]) free(tags->v[i]); | ||
481 | } | ||
482 | |||
483 | amb | 401 | if(tags->ntags) |
484 | { | ||
485 | free(tags->k); | ||
486 | free(tags->v); | ||
487 | } | ||
488 | |||
489 | amb | 393 | free(tags); |
490 | } | ||
491 | |||
492 | |||
493 | /*++++++++++++++++++++++++++++++++++++++ | ||
494 | Apply a set of tagging rules to a set of tags. | ||
495 | |||
496 | TagList *ApplyTaggingRules Returns the list of output tags after modification. | ||
497 | |||
498 | TaggingRuleList *rules The tagging rules to apply. | ||
499 | |||
500 | TagList *tags The tags to be modified. | ||
501 | ++++++++++++++++++++++++++++++++++++++*/ | ||
502 | |||
503 | TagList *ApplyTaggingRules(TaggingRuleList *rules,TagList *tags) | ||
504 | { | ||
505 | amb | 401 | TagList *result=NewTagList(); |
506 | amb | 393 | int i,j; |
507 | |||
508 | for(i=0;i<rules->nrules;i++) | ||
509 | { | ||
510 | if(rules->rules[i].k && rules->rules[i].v) | ||
511 | { | ||
512 | for(j=0;j<tags->ntags;j++) | ||
513 | if(!strcmp(tags->k[j],rules->rules[i].k) && !strcmp(tags->v[j],rules->rules[i].v)) | ||
514 | apply_actions(&rules->rules[i],j,tags,result); | ||
515 | } | ||
516 | else if(rules->rules[i].k && !rules->rules[i].v) | ||
517 | { | ||
518 | for(j=0;j<tags->ntags;j++) | ||
519 | if(!strcmp(tags->k[j],rules->rules[i].k)) | ||
520 | apply_actions(&rules->rules[i],j,tags,result); | ||
521 | } | ||
522 | else if(!rules->rules[i].k && rules->rules[i].v) | ||
523 | { | ||
524 | for(j=0;j<tags->ntags;j++) | ||
525 | if(!strcmp(tags->v[j],rules->rules[i].v)) | ||
526 | apply_actions(&rules->rules[i],j,tags,result); | ||
527 | } | ||
528 | else /* if(!rules->rules[i].k && !rules->rules[i].v) */ | ||
529 | { | ||
530 | for(j=0;j<tags->ntags;j++) | ||
531 | apply_actions(&rules->rules[i],j,tags,result); | ||
532 | } | ||
533 | } | ||
534 | |||
535 | return(result); | ||
536 | } | ||
537 | |||
538 | |||
539 | /*++++++++++++++++++++++++++++++++++++++ | ||
540 | Apply a set of actions to a matching tag. | ||
541 | |||
542 | TaggingRule *rule The rule that matched (containing the actions). | ||
543 | |||
544 | int match The matching tag number. | ||
545 | |||
546 | TagList *input The input tags. | ||
547 | |||
548 | TagList *output The output tags. | ||
549 | ++++++++++++++++++++++++++++++++++++++*/ | ||
550 | |||
551 | static void apply_actions(TaggingRule *rule,int match,TagList *input,TagList *output) | ||
552 | { | ||
553 | int i; | ||
554 | |||
555 | for(i=0;i<rule->nactions;i++) | ||
556 | { | ||
557 | char *k,*v; | ||
558 | |||
559 | if(rule->actions[i].k) | ||
560 | k=rule->actions[i].k; | ||
561 | else | ||
562 | k=input->k[match]; | ||
563 | |||
564 | if(rule->actions[i].v) | ||
565 | v=rule->actions[i].v; | ||
566 | else | ||
567 | v=input->v[match]; | ||
568 | |||
569 | if(rule->actions[i].output) | ||
570 | ModifyTag(output,k,v); | ||
571 | else | ||
572 | ModifyTag(input,k,v); | ||
573 | } | ||
574 | } |
Properties
Name | Value |
---|---|
cvs:description | Functions for reading the tag transformation rules and applying them. |