r38824 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r38823‎ | r38824 | r38825 >
Date:00:23, 8 August 2008
Author:river
Status:old
Tags:
Comment:
- delete afparser, afutils; unused
- cleanups for affunctions, aftypes
Modified paths:
  • /trunk/extensions/AbuseFilter/parser_native/affunctions.cpp (modified) (history)
  • /trunk/extensions/AbuseFilter/parser_native/affunctions.h (modified) (history)
  • /trunk/extensions/AbuseFilter/parser_native/afparser.cpp (deleted) (history)
  • /trunk/extensions/AbuseFilter/parser_native/afparser.h (deleted) (history)
  • /trunk/extensions/AbuseFilter/parser_native/aftypes.cpp (modified) (history)
  • /trunk/extensions/AbuseFilter/parser_native/aftypes.h (modified) (history)
  • /trunk/extensions/AbuseFilter/parser_native/afutils.cpp (deleted) (history)
  • /trunk/extensions/AbuseFilter/parser_native/afutils.h (deleted) (history)

Diff [purge]

Index: trunk/extensions/AbuseFilter/parser_native/afparser.cpp
@@ -1,234 +0,0 @@
2 -#include "afparser.h"
3 -#include <ctype.h>
4 -
5 -struct ParseStatus {
6 - AFPToken newToken;
7 - string code;
8 - unsigned int len;
9 -
10 - ParseStatus() {code = ""; len = 0;}
11 -
12 - ParseStatus( AFPToken nt, string sc, int l ) {
13 - newToken = nt;
14 - code = sc;
15 - len = l;
16 - }
17 -};
18 -
19 -bool af_nextToken( ParseStatus* ps );
20 -
21 -vector<AFPToken> af_parse( string code ) {
22 - vector<AFPToken> ret;
23 - AFPToken curTok;
24 - ParseStatus ps;
25 - int pos = 0;
26 -
27 - ps.len = code.size();
28 - ps.code = code;
29 -
30 - while ( af_nextToken( &ps ) ) {
31 - ret.push_back( curTok = ps.newToken );
32 -
33 -// printf( "New token. Type %d, value %s\n", curTok.type, curTok.value.c_str() );
34 -
35 - if (curTok.type == T_NONE) {
36 - break;
37 - }
38 - }
39 -
40 - return ret;
41 -}
42 -
43 -bool af_nextToken( ParseStatus* ps ) {
44 - AFPToken tok;
45 - unsigned int pos = 0;
46 - string code = ps->code;
47 - unsigned int len = ps->len;
48 -
49 - if (code.size() == 0) {
50 - tok = AFPToken( T_NONE, "", len );
51 - *ps = ParseStatus( tok, code, len );
52 - return true;
53 - }
54 -
55 - while (isspace( code[0] )) {
56 - code = code.substr(1);
57 - }
58 -
59 - if (code.size() == 0) {
60 - tok = AFPToken( T_NONE, "", len );
61 - *ps = ParseStatus( tok, code, len );
62 - return true;
63 - }
64 -
65 - pos = len - code.size();
66 -
67 - // Comma
68 - if (code[0] == ',') {
69 - tok = AFPToken( T_COMMA, code.substr(0,1), pos );
70 - code = code.substr(1);
71 - *ps = ParseStatus( tok, code, len );
72 - return true;
73 - }
74 -
75 - // Parens
76 - if (code[0] == '(' || code[0] == ')') {
77 - tok = AFPToken( T_BRACE, code.substr(0,1), pos );
78 - code = code.substr(1);
79 - *ps = ParseStatus( tok, code, len );
80 - return true;
81 - }
82 -
83 - // Strings
84 - if ( code[0] == '"' || code[0] == '\'' ) {
85 - char type = code[0];
86 - code = code.substr(1);
87 - string s = "";
88 -
89 - while (code.size() > 0) {
90 - if ( code[0] == type ) {
91 - code = code.substr(1);
92 - tok = AFPToken( T_STRING, s, pos );
93 - *ps = ParseStatus( tok, code, len );
94 - return true;
95 - }
96 -
97 - if ( code[0] == '\\' ) {
98 - if (code[1] == '\\') {
99 - s.append( 1, '\\' );
100 - } else if (code[1] == type) {
101 - s.append( 1, type );
102 - } else if (code[1] == 'n' ) {
103 - s.append( 1, '\n' );
104 - } else if (code[1] == 'r' ) {
105 - s.append( 1, '\r' );
106 - } else if (code[1] == 't' ) {
107 - s.append( 1, '\t' );
108 - } else {
109 - s.append( 1, code[1] );
110 - }
111 - code = code.substr(2);
112 - } else {
113 - s.append( 1, code[0] );
114 - code = code.substr(1);
115 - }
116 - }
117 -
118 - throw AFPException( "Unclosed string" );
119 - }
120 -
121 - // Operators
122 - // Parens and commas have special meanings.
123 - if (ispunct( code[0] ) && code[0] != '(' && code[0] != ',' ) {
124 - string s = "";
125 -
126 - while ( code.length() > 0 && ispunct(code[0]) ) {
127 - s.append( 1, code[0] );
128 - code = code.substr(1);
129 - }
130 -
131 - if (!isValidOp( s )) {
132 - throw AFPException( "Invalid operator %s", s );
133 - }
134 -
135 - tok = AFPToken( T_OP, s, pos );
136 - *ps = ParseStatus( tok, code, len );
137 - return true;
138 - }
139 -
140 - // Raw numbers
141 - if ( isdigit( code[0] ) ) {
142 - string s = "";
143 -
144 - while ( code.length() > 0 && isDigitOrDot( code[0] ) ) {
145 - s.append( 1, code[0] );
146 - code = code.substr(1);
147 - }
148 -
149 - tok = AFPToken( T_NUMBER, s, pos );
150 - *ps = ParseStatus( tok, code, len );
151 - return true;
152 - }
153 -
154 - if ( isValidIdSymbol( code[0] ) ) {
155 - string op = "";
156 -
157 - while (code.length() > 0 && isValidIdSymbol( code[0]) ) {
158 - op.append( 1, code[0] );
159 - code = code.substr(1);
160 - }
161 -
162 - int type = T_ID;
163 - if (isKeyword(op)) {
164 - type = T_KEYWORD;
165 - }
166 -
167 - tok = AFPToken( type, op, pos );
168 - *ps = ParseStatus( tok, code, len );
169 - return true;
170 - }
171 -
172 - throw AFPException( "Unrecognised token" );
173 -}
174 -
175 -bool isDigitOrDot( char chr ) {
176 - return isdigit(chr) || chr == '.';
177 -}
178 -
179 -bool isValidIdSymbol( char chr ) {
180 - return isalnum(chr) || chr == '_';
181 -}
182 -
183 -bool isValidOp( string op ) {
184 - vector<string> validOps = getValidOps();
185 -
186 - return isInVector( op, validOps );
187 -}
188 -
189 -bool isKeyword( string id ) {
190 - vector<string> keywords = getKeywords();
191 -
192 - return isInVector( id, keywords );
193 -}
194 -
195 -vector<string> getValidOps() {
196 - static vector<string> validOps;
197 -
198 - if (validOps.empty()) {
199 - validOps.push_back( "!" );
200 - validOps.push_back( "*" );
201 - validOps.push_back( "**" );
202 - validOps.push_back( "/" );
203 - validOps.push_back( "+" );
204 - validOps.push_back( "-" );
205 - validOps.push_back( "%" );
206 - validOps.push_back( "&" );
207 - validOps.push_back( "|" );
208 - validOps.push_back( "^" );
209 - validOps.push_back( "<" );
210 - validOps.push_back( ">" );
211 - validOps.push_back( ">=" );
212 - validOps.push_back( "<=" );
213 - validOps.push_back( "==" );
214 - validOps.push_back( "!=" );
215 - validOps.push_back( "=" );
216 - validOps.push_back( "===" );
217 - validOps.push_back( "!==" );
218 - }
219 -
220 - return validOps;
221 -}
222 -
223 -vector<string> getKeywords() {
224 - static vector<string> keywords;
225 -
226 - if (keywords.size() == 0) {
227 - keywords.push_back( "in" );
228 - keywords.push_back( "like" );
229 - keywords.push_back( "true" );
230 - keywords.push_back( "false" );
231 - keywords.push_back( "null" );
232 - }
233 -
234 - return keywords;
235 -}
Index: trunk/extensions/AbuseFilter/parser_native/afutils.cpp
@@ -1,131 +0,0 @@
2 -#include "afutils.h"
3 -#include <math.h>
4 -#include <boost/regex.hpp>
5 -#include <boost/regex/icu.hpp>
6 -
7 -AFPData af_boolInvert( AFPData value ) {
8 - bool bVal = !value.toBool();
9 -
10 - AFPData d(bVal);
11 -
12 - return d;
13 -}
14 -
15 -AFPData af_pow( AFPData base, AFPData exponent ) {
16 - float b = base.toFloat();
17 - float e = exponent.toFloat();
18 -
19 - float result = pow(b,e);
20 -
21 - return AFPData(result);
22 -}
23 -
24 -AFPData af_keywordIn( AFPData needle, AFPData haystack ) {
25 - string n = needle.toString();
26 - string h = haystack.toString();
27 -
28 - bool result = h.find(n,0) != h.npos;
29 -
30 - return AFPData(result);
31 -}
32 -
33 -AFPData af_unaryMinus( AFPData data ) {
34 - float v = data.toFloat();
35 -
36 - return AFPData(-v);
37 -}
38 -
39 -AFPData af_boolOp( AFPData a, AFPData b, string op ) {
40 - bool v1 = a.toBool();
41 - bool v2 = b.toBool();
42 -
43 - if (op == "|") {
44 - return AFPData( v1 || v2 );
45 - } else if (op == "&") {
46 - return AFPData( v1 && v2 );
47 - } else if (op == "^") {
48 - return AFPData( (v1 || v2) && !(v1 && v2) );
49 - }
50 -
51 - throw AFPException( "Invalid boolean operation." );
52 -}
53 -
54 -AFPData af_compareOp( AFPData a, AFPData b, string op ) {
55 - string s1 = a.toString();
56 - string s2 = b.toString();
57 -
58 - float f1 = a.toFloat();
59 - float f2 = b.toFloat();
60 -
61 - unsigned int t1 = a.getType();
62 - unsigned int t2 = b.getType();
63 -
64 - if (op == "==") {
65 - return AFPData( s1 == s2 );
66 - } else if (op == "!=") {
67 - return AFPData( s1 != s2 );
68 - } else if (op == "===") {
69 - return AFPData( s1 == s2 && t1 == t2 );
70 - } else if (op == "!==") {
71 - return AFPData( s1 != s2 || t1 != t2 );
72 - } else if (op == ">") {
73 - return AFPData( f1 > f2 );
74 - } else if (op == "<") {
75 - return AFPData( f1 < f2 );
76 - } else if (op == ">=") {
77 - return AFPData( f1 >= f2 );
78 - } else if (op == "<=") {
79 - return AFPData( f1 <= f2 );
80 - }
81 - throw AFPException( "Invalid comparison type" );
82 -}
83 -
84 -AFPData af_mulRel( AFPData a, AFPData b, string op ) {
85 - float f1 = a.toFloat();
86 - float f2 = b.toFloat();
87 -
88 - if (op == "*") {
89 - return AFPData( f1 * f2 );
90 - } else if (op == "/") {
91 - return AFPData( f1 / f2 );
92 - } else if (op == "%") {
93 - int i1 = a.toInt();
94 - int i2 = b.toInt();
95 -
96 - return AFPData( (double)(i1 % i2) );
97 - }
98 -
99 - throw AFPException( "Invalid multiplication-related operator" );
100 -}
101 -
102 -AFPData af_sum( AFPData a, AFPData b ) {
103 - if (a.getType() == D_STRING || b.getType() == D_STRING) {
104 - return AFPData( a.toString() + b.toString() );
105 - } else {
106 - return AFPData( a.toFloat() + b.toFloat() );
107 - }
108 -}
109 -
110 -AFPData af_sub( AFPData a, AFPData b ) {
111 - return AFPData( a.toFloat() - b.toFloat() );
112 -}
113 -
114 -AFPData af_keyword( string keyword, AFPData a, AFPData b ) {
115 - if (keyword == "in") {
116 - string needle = a.toString();
117 - string haystack = b.toString();
118 -
119 - bool result = (haystack.find( needle, 0 ) != haystack.npos);
120 -
121 - return AFPData( result );
122 - } else if (keyword == "like") {
123 - boost::u32regex rx = boost::make_u32regex( UnicodeString(b.toString().c_str()) );
124 - string test = a.toString();
125 -
126 - bool result = boost::u32regex_match( test, rx );
127 -
128 - return AFPData( result );
129 - }
130 -
131 - throw AFPException( "Unknown keyword %s", keyword );
132 -}
Index: trunk/extensions/AbuseFilter/parser_native/afparser.h
@@ -1,19 +0,0 @@
2 -#ifndef AFPARSER_H
3 -#define AFPARSER_H
4 -
5 -#include "aftypes.h"
6 -#include <vector>
7 -#include "afutils.h"
8 -
9 -vector<AFPToken> af_parse( string code );
10 -
11 -bool isDigitOrDot( char chr );
12 -bool isValidIdSymbol( char chr );
13 -
14 -vector<string> getValidOps();
15 -vector<string> getKeywords();
16 -
17 -bool isKeyword( string id );
18 -bool isValidOp( string op );
19 -
20 -#endif /* !AFPARSER_H */
Index: trunk/extensions/AbuseFilter/parser_native/afutils.h
@@ -1,18 +0,0 @@
2 -#ifndef AFUTILS_H
3 -#define AFUTILS_H
4 -
5 -#include "aftypes.h"
6 -#include <vector>
7 -
8 -AFPData af_boolInvert( AFPData value );
9 -AFPData af_pow( AFPData base, AFPData exponent );
10 -AFPData af_keywordIn( AFPData needle, AFPData haystack );
11 -AFPData af_unaryMinus( AFPData data );
12 -AFPData af_boolOp( AFPData a, AFPData b, string op );
13 -AFPData af_compareOp( AFPData a, AFPData b, string op );
14 -AFPData af_mulRel( AFPData a, AFPData b, string op );
15 -AFPData af_sum( AFPData a, AFPData b );
16 -AFPData af_sub( AFPData a, AFPData b );
17 -AFPData af_keyword( string keyword, AFPData a, AFPData b );
18 -
19 -#endif /* !AFUTILS_H */
Index: trunk/extensions/AbuseFilter/parser_native/aftypes.cpp
@@ -77,7 +77,7 @@
7878 return *this;
7979 }
8080
81 -bool isInVector( string needle, vector<string> haystack ) {
 81+bool isInVector(std::string const &needle, std::vector<std::string> const &haystack) {
8282 return std::find(haystack.begin(), haystack.end(), needle) != haystack.end();
8383 }
8484
Index: trunk/extensions/AbuseFilter/parser_native/affunctions.cpp
@@ -11,12 +11,13 @@
1212
1313 #define EQUIVSET_LOC "equivset.txt"
1414
15 -AFPData af_count( vector<AFPData> args ) {
 15+AFPData
 16+af_count(std::vector<AFPData> const &args) {
1617 if (!args.size()) {
1718 throw AFPException( "Not enough arguments to count" );
1819 }
1920
20 - string needle,haystack;
 21+ string needle, haystack;
2122
2223 if (args.size() < 2) {
2324 needle = ",";
@@ -31,7 +32,7 @@
3233
3334 while (last_pos != haystack.npos) {
3435 count++;
35 - last_pos = haystack.find( needle, last_pos );
 36+ last_pos = haystack.find(needle, last_pos);
3637 }
3738
3839 // One extra was added, but one extra is needed if only one arg was supplied.
@@ -42,7 +43,8 @@
4344 return AFPData((long int)count);
4445 }
4546
46 -AFPData af_norm( vector<AFPData> args ) {
 47+AFPData
 48+af_norm(vector<AFPData> const &args) {
4749 if (!args.size()) {
4850 throw AFPException( "Not enough arguments to norm" );
4951 }
@@ -51,15 +53,16 @@
5254
5355 string::const_iterator p, charStart, end;
5456 int chr = 0,lastchr = 0;
55 - map<int,int> &equivSet = getEquivSet();
 57+ map<int,int> const &equivSet = getEquivSet();
5658 string result;
5759
5860 p = orig.begin();
5961 end = orig.end();
6062
6163 while (chr = next_utf8_char( p, charStart, end )) {
62 - if (equivSet.find(chr) != equivSet.end()) {
63 - chr = equivSet[chr];
 64+ std::map<int, int>::const_iterator it;
 65+ if ((it = equivSet.find(chr)) != equivSet.end()) {
 66+ chr = it->second;
6467 }
6568
6669 if (chr != lastchr && isalnum(chr)) {
@@ -72,7 +75,8 @@
7376 return AFPData(result);
7477 }
7578
76 -string rmdoubles( string orig ) {
 79+string
 80+rmdoubles(std::string const &orig) {
7781 string::const_iterator p, charStart, end;
7882 int chr,lastchr = 0;
7983 string result;
@@ -90,7 +94,8 @@
9195 return result;
9296 }
9397
94 -AFPData af_specialratio( vector<AFPData> args ) {
 98+AFPData
 99+af_specialratio(std::vector<AFPData> const &args) {
95100 if (!args.size()) {
96101 throw AFPException( "Not enough arguments to specialratio" );
97102 }
@@ -113,18 +118,17 @@
114119 return AFPData(ratio);
115120 }
116121
117 -AFPData af_rmspecials( vector<AFPData> args ) {
 122+AFPData
 123+af_rmspecials(std::vector<AFPData> const &args) {
118124 if (!args.size()) {
119125 throw AFPException( "Not enough arguments to rmspecials" );
120126 }
121127
122 - string orig = args[0].toString();
123 - string result = rmspecials(orig);
124 -
125 - return AFPData(result);
 128+ return AFPData(rmspecials(args[0].toString()));
126129 }
127130
128 -string rmspecials( string orig ) {
 131+std::string
 132+rmspecials(std::string const &orig) {
129133 string::const_iterator p, charStart, end;
130134 int chr = 0;
131135 string result;
@@ -140,7 +144,8 @@
141145 return result;
142146 }
143147
144 -AFPData af_ccnorm( vector<AFPData> args ) {
 148+AFPData
 149+af_ccnorm(std::vector<AFPData> const &args) {
145150 if (!args.size()) {
146151 throw AFPException( "Not enough arguments to ccnorm" );
147152 }
@@ -148,17 +153,17 @@
149154 return AFPData( confusable_character_normalise( args[0].toString() ) );
150155 }
151156
152 -AFPData af_rmdoubles( vector<AFPData> args ) {
 157+AFPData
 158+af_rmdoubles(std::vector<AFPData> const &args) {
153159 if (!args.size()) {
154160 throw AFPException( "Not enough arguments to rmdoubles" );
155161 }
156162
157 - string result = rmdoubles( args[0].toString() );
158 -
159 - return AFPData(result);
 163+ return AFPData(rmdoubles(args[0].toString()));
160164 }
161165
162 -AFPData af_length( vector<AFPData> args ) {
 166+AFPData
 167+af_length(std::vector<AFPData> const &args) {
163168 if (!args.size()) {
164169 throw AFPException( "Not enough arguments to lcase" );
165170 }
@@ -166,7 +171,8 @@
167172 return AFPData( (long int)utf8_strlen(args[0].toString()) );
168173 }
169174
170 -AFPData af_lcase( vector<AFPData> args ) {
 175+AFPData
 176+af_lcase(std::vector<AFPData> const &args) {
171177 if (!args.size()) {
172178 throw AFPException( "Not enough arguments to lcase" );
173179 }
@@ -174,18 +180,20 @@
175181 return AFPData(utf8_tolower(args[0].toString()));
176182 }
177183
178 -string confusable_character_normalise( string orig ) {
 184+std::string
 185+confusable_character_normalise(std::string const &orig) {
179186 string::const_iterator p, charStart, end;
180187 int chr;
181 - map<int,int> &equivSet = getEquivSet();
 188+ map<int,int> const &equivSet = getEquivSet();
182189 string result;
183190
184191 p = orig.begin();
185192 end = orig.end();
186193
187194 while (chr = next_utf8_char( p, charStart, end )) {
188 - if (equivSet.find(chr) != equivSet.end()) {
189 - chr = equivSet[chr];
 195+ map<int, int>::const_iterator it;
 196+ if ((it = equivSet.find(chr)) != equivSet.end()) {
 197+ chr = it->second;
190198 }
191199
192200 result.append(codepointToUtf8(chr));
@@ -194,7 +202,7 @@
195203 return result;
196204 }
197205
198 -map<int,int> &
 206+map<int,int> const &
199207 getEquivSet() {
200208 static map<int,int> equivSet;
201209 // Map of codepoint:codepoint
@@ -236,7 +244,8 @@
237245 // Weak UTF-8 decoder
238246 // Will return garbage on invalid input (overshort sequences, overlong sequences, etc.)
239247 // Stolen from wikidiff2 extension by Tim Starling (no point in reinventing the wheel)
240 -int next_utf8_char(std::string::const_iterator & p, std::string::const_iterator & charStart,
 248+int
 249+next_utf8_char(std::string::const_iterator & p, std::string::const_iterator & charStart,
241250 std::string::const_iterator end)
242251 {
243252 int c=0;
@@ -287,18 +296,6 @@
288297 int skip = 1;
289298
290299 skip = U8_LENGTH(*it);
291 -#if 0
292 - if (*it >= 0xc0) {
293 - if (*it < 0xe0)
294 - skip = 1;
295 - else if (*it < 0xf0)
296 - skip = 2;
297 - else
298 - skip = 3;
299 - } else
300 - skip = 1;
301 -#endif
302 -
303300 if (it + skip >= end)
304301 return ret; /* end of string */
305302
@@ -311,7 +308,8 @@
312309 /*
313310 * This could almost certainly be done in a nicer way.
314311 */
315 -std::string utf8_tolower(std::string const &s)
 312+std::string
 313+utf8_tolower(std::string const &s)
316314 {
317315 std::vector<UChar> ustring;
318316 UErrorCode error = U_ZERO_ERROR;
@@ -338,7 +336,8 @@
339337 }
340338
341339 // Ported from MediaWiki core function in PHP.
342 -string codepointToUtf8( int codepoint ) {
 340+string
 341+codepointToUtf8(int codepoint) {
343342 string ret;
344343
345344 if(codepoint < 0x80) {
Index: trunk/extensions/AbuseFilter/parser_native/aftypes.h
@@ -140,6 +140,6 @@
141141 return s;
142142 }
143143
144 -bool isInVector( string needle, vector<string> haystack );
 144+bool isInVector(std::string const &needle, std::vector<std::string> const &haystack);
145145
146146 #endif /* !AFTYPES_H */
Index: trunk/extensions/AbuseFilter/parser_native/affunctions.h
@@ -5,23 +5,23 @@
66 #include <map>
77 #include <vector>
88
9 -AFPData af_length(std::vector<AFPData> args);
10 -AFPData af_lcase(std::vector<AFPData> args);
11 -AFPData af_ccnorm(std::vector<AFPData> args);
12 -AFPData af_rmdoubles(std::vector<AFPData> args);
13 -AFPData af_specialratio(std::vector<AFPData> args);
14 -AFPData af_rmspecials(std::vector<AFPData> args);
15 -AFPData af_norm(std::vector<AFPData> args);
16 -AFPData af_count(std::vector<AFPData> args);
 9+AFPData af_length(std::vector<AFPData> const &args);
 10+AFPData af_lcase(std::vector<AFPData> const &args);
 11+AFPData af_ccnorm(std::vector<AFPData> const &args);
 12+AFPData af_rmdoubles(std::vector<AFPData> const &args);
 13+AFPData af_specialratio(std::vector<AFPData> const &args);
 14+AFPData af_rmspecials(std::vector<AFPData> const &args);
 15+AFPData af_norm(std::vector<AFPData> const &args);
 16+AFPData af_count(std::vector<AFPData> const &args);
1717
18 -map<int,int> &getEquivSet();
 18+map<int,int> const &getEquivSet();
1919 int next_utf8_char(std::string::const_iterator & p, std::string::const_iterator & charStart, std::string::const_iterator end);
2020 string codepointToUtf8( int codepoint );
21 -string confusable_character_normalise( string orig );
 21+string confusable_character_normalise(std::string const &orig);
2222 vector<AFPData> makeFuncArgList( AFPData arg );
23 -AFPData callFunction( string name, AFPData arg );
24 -string rmdoubles( string orig );
25 -string rmspecials( string orig );
 23+AFPData callFunction(string const &name, AFPData arg);
 24+string rmdoubles(string const &orig);
 25+string rmspecials(string const &orig);
2626 std::size_t utf8_strlen(std::string const &s);
2727 std::string utf8_tolower(std::string const &s);
2828

Status & tagging log