diff options
| -rw-r--r-- | nameblocker.sp | 242 |
1 files changed, 153 insertions, 89 deletions
diff --git a/nameblocker.sp b/nameblocker.sp index 366abf9..554b086 100644 --- a/nameblocker.sp +++ b/nameblocker.sp | |||
| @@ -1,4 +1,22 @@ | |||
| 1 | // Notes: | ||
| 2 | // Memory allocated via the "new" keyword IS garbage collected. Handles are not. Close handles when you're done with them | ||
| 3 | // Handles are closed when the plugin is unloaded, so if the lifetime of a handle is the plugin's lifetime, don't worry about closing it | ||
| 4 | // The contents of ArrayList objects are lost on map transition / server restart. Any persistent data should be stored in a | ||
| 5 | // key-value file OR in a database | ||
| 6 | |||
| 7 | // Basically every string function will add a null terminator, so add `+ 1` to the end of any defined size string definition | ||
| 8 | // It is possible to throw an error with the ThrowError function, but anything that would bother should probably disable the | ||
| 9 | // plugin entirely, so SetFailState is better | ||
| 10 | |||
| 11 | // Large local var allocations if done commonly should be made static. Increases baseline memory usage, but lowers time spent | ||
| 12 | // allocating memory. That being said, don't bother unless it's actually a problem. Name checks should be relatively | ||
| 13 | // infrequent, and everything else exponentially less frequent. Dropping a frame or 2 to allocate 2048 bytes of memory | ||
| 14 | // every century shouldn't be the end of the world | ||
| 15 | |||
| 16 | // | ||
| 17 | |||
| 1 | #pragma newdecls required | 18 | #pragma newdecls required |
| 19 | #pragma semicolon 1 | ||
| 2 | 20 | ||
| 3 | #include <sourcemod> | 21 | #include <sourcemod> |
| 4 | #include <regex> | 22 | #include <regex> |
| @@ -26,9 +44,6 @@ enum OperatingMode { | |||
| 26 | 44 | ||
| 27 | ArrayList regexlist; | 45 | ArrayList regexlist; |
| 28 | ArrayList patternlist; | 46 | ArrayList patternlist; |
| 29 | // Note: Contents of ArrayLists are lost on map change / reload. I should store everything in a database, | ||
| 30 | // then use the database to populate the list whenever it is cleared | ||
| 31 | |||
| 32 | Database db; | 47 | Database db; |
| 33 | 48 | ||
| 34 | ConVar gcvarOperMode; static const char OPERMODENAME[] = "nameblock_OperatingMode"; const OperatingMode DEFAULTOPERMODE = OP_KICK; | 49 | ConVar gcvarOperMode; static const char OPERMODENAME[] = "nameblock_OperatingMode"; const OperatingMode DEFAULTOPERMODE = OP_KICK; |
| @@ -36,25 +51,69 @@ ConVar gcvarAdmCmdFlag; static const char ADMCMDFLAGNAME[] = "nameb | |||
| 36 | ConVar gcvarRegexCompFlags; static const char REGEXCOMPFLAGSNAME[] = "nameblock_RegexCompilationFlags"; const int DEFAULTREGEXCOMPFLAGS = (PCRE_CASELESS | PCRE_DOTALL | PCRE_EXTENDED | PCRE_UTF8); | 51 | ConVar gcvarRegexCompFlags; static const char REGEXCOMPFLAGSNAME[] = "nameblock_RegexCompilationFlags"; const int DEFAULTREGEXCOMPFLAGS = (PCRE_CASELESS | PCRE_DOTALL | PCRE_EXTENDED | PCRE_UTF8); |
| 37 | ConVar gcvarAmdImmFlag; static const char ADMINIMMUNITYFLAGNAME[] = "nameblock_AdminImmunityFlag"; const int DEFAULTADMIMMFLAG = ADMFLAG_GENERIC; | 52 | ConVar gcvarAmdImmFlag; static const char ADMINIMMUNITYFLAGNAME[] = "nameblock_AdminImmunityFlag"; const int DEFAULTADMIMMFLAG = ADMFLAG_GENERIC; |
| 38 | 53 | ||
| 54 | |||
| 55 | |||
| 56 | // Logs and throws an error with the same message of upto 2048 characters | ||
| 57 | void logAndFail(const char[] format, any ...) { | ||
| 58 | char buf[2048 + 1]; | ||
| 59 | VFormat(buf, sizeof(buf), format, 2); | ||
| 60 | |||
| 61 | LogError(buf); | ||
| 62 | SetFailState(buf); | ||
| 63 | } | ||
| 64 | |||
| 65 | // Concatenate arguments into a single buffer | ||
| 66 | int concatArgs(char[] buf, int maxbuflen, int maxarglen, int end, int start=1) { | ||
| 67 | if(maxbuflen <= 0 || start < 0) return -1; | ||
| 68 | |||
| 69 | char[] arg = new char[maxarglen]; | ||
| 70 | char[] tmp = new char[maxbuflen]; | ||
| 71 | |||
| 72 | GetCmdArg(start, tmp, maxarglen); // Priming the first argument to prevent weirdness | ||
| 73 | for(int i = start + 1; i <= end; i++) { | ||
| 74 | GetCmdArg(i, arg, maxarglen); | ||
| 75 | Format(tmp, maxbuflen, "%s %s", tmp, arg); | ||
| 76 | } | ||
| 77 | |||
| 78 | return strcopy(buf, maxbuflen, tmp); | ||
| 79 | } | ||
| 80 | |||
| 81 | // Register a convar who's default value is an integer | ||
| 39 | int registerIntConVar(ConVar& cv, int defaultVal, const char[] name, const char[] desc) { | 82 | int registerIntConVar(ConVar& cv, int defaultVal, const char[] name, const char[] desc) { |
| 40 | static char tmp[32]; // Consider this a byte array | 83 | char tmp[32]; // Consider this a byte array |
| 41 | Format(tmp, sizeof(tmp), "%d", defaultVal); | 84 | Format(tmp, sizeof(tmp), "%d", defaultVal); |
| 85 | |||
| 42 | cv = CreateConVar(name, tmp, desc); | 86 | cv = CreateConVar(name, tmp, desc); |
| 87 | if(cv == null) return -1; | ||
| 43 | cv.IntValue = defaultVal; | 88 | cv.IntValue = defaultVal; |
| 44 | 89 | ||
| 45 | return 0; | 90 | return 0; |
| 46 | } | 91 | } |
| 47 | 92 | ||
| 93 | // `registerIntConVar` wrapper. Calls `logAndFail` if the convar couldn't be registered | ||
| 94 | void xRegisterIntConVar(ConVar& cv, int defaultVal, const char[] name, const char[] desc) { | ||
| 95 | if(registerIntConVar(cv, defaultVal, name, desc)) logAndFail("Could not register cvar \"%s\"", name); | ||
| 96 | } | ||
| 97 | |||
| 98 | |||
| 99 | |||
| 48 | public void OnAllPluginsLoaded() { | 100 | public void OnAllPluginsLoaded() { |
| 49 | // Initialize and populate datatypes | 101 | // Initialize and populate datatypes |
| 50 | regexlist = new ArrayList(ByteCountToCells(HANDLE_SIZE)); | 102 | regexlist = new ArrayList(ByteCountToCells(HANDLE_SIZE)); |
| 103 | if(regexlist == null) logAndFail("Could not initialize regexlist ArrayList"); | ||
| 104 | |||
| 51 | patternlist = new ArrayList(ByteCountToCells(PATTERN_MAX_LEN)); | 105 | patternlist = new ArrayList(ByteCountToCells(PATTERN_MAX_LEN)); |
| 52 | // db = | 106 | if(patternlist == null) logAndFail("Could not initialize patternlist ArrayList"); |
| 107 | |||
| 108 | char sqlerr[256 + 1]; | ||
| 109 | db = SQL_DefConnect(sqlerr, sizeof(sqlerr)); // Default connect until I get a little more acquainted with sm's sql api | ||
| 110 | if(db == null) logAndFail("Could not connect to sql database: %s", sqlerr); | ||
| 53 | 111 | ||
| 54 | registerIntConVar(gcvarOperMode, view_as<int>(DEFAULTOPERMODE), OPERMODENAME, "Operating mode (disabled, kick, ban, etc.)"); | 112 | // Register convars |
| 55 | registerIntConVar(gcvarAdmCmdFlag, DEFAULTADMCMDFLAG, ADMCMDFLAGNAME, "Admin flag to modify pattern list"); | 113 | xRegisterIntConVar(gcvarOperMode, view_as<int>(DEFAULTOPERMODE), OPERMODENAME, "Operating mode (disabled, kick, ban, etc.)"); |
| 56 | registerIntConVar(gcvarRegexCompFlags, DEFAULTREGEXCOMPFLAGS, REGEXCOMPFLAGSNAME, "Regular expression compilation flags"); | 114 | xRegisterIntConVar(gcvarAdmCmdFlag, DEFAULTADMCMDFLAG, ADMCMDFLAGNAME, "Admin flag to modify pattern list"); |
| 57 | registerIntConVar(gcvarAmdImmFlag, DEFAULTADMIMMFLAG, ADMINIMMUNITYFLAGNAME, "Admin immunity flag"); | 115 | xRegisterIntConVar(gcvarRegexCompFlags, DEFAULTREGEXCOMPFLAGS, REGEXCOMPFLAGSNAME, "Regular expression compilation flags"); |
| 116 | xRegisterIntConVar(gcvarAmdImmFlag, DEFAULTADMIMMFLAG, ADMINIMMUNITYFLAGNAME, "Admin immunity flag"); | ||
| 58 | 117 | ||
| 59 | AutoExecConfig(true, "nameblocker_cvars"); | 118 | AutoExecConfig(true, "nameblocker_cvars"); |
| 60 | 119 | ||
| @@ -82,12 +141,14 @@ public Action registerPattern(int client, int args) { | |||
| 82 | } | 141 | } |
| 83 | 142 | ||
| 84 | char pattern[PATTERN_MAX_LEN]; | 143 | char pattern[PATTERN_MAX_LEN]; |
| 85 | GetCmdArg(1, pattern, sizeof(pattern)); | 144 | if(concatArgs(pattern, sizeof(pattern), PATTERN_MAX_LEN, args) <= 0) { |
| 86 | // TODO: Error handling | 145 | ReplyToCommand(client, "Error: could not get argument list"); |
| 146 | return Plugin_Handled; | ||
| 147 | } | ||
| 87 | 148 | ||
| 88 | if(insertPattern(pattern, regexlist.Length - 1)) { | 149 | if(insertPattern(pattern, regexlist.Length)) { |
| 89 | ReplyToCommand(client, "Error: could not register pattern"); | 150 | ReplyToCommand(client, "Error: could not register pattern"); |
| 90 | return Plugin_Handled | 151 | return Plugin_Handled; |
| 91 | } | 152 | } |
| 92 | 153 | ||
| 93 | return Plugin_Handled; | 154 | return Plugin_Handled; |
| @@ -99,7 +160,7 @@ public Action deletePattern(int client, int args) { | |||
| 99 | return Plugin_Handled; | 160 | return Plugin_Handled; |
| 100 | } | 161 | } |
| 101 | 162 | ||
| 102 | int index | 163 | int index; |
| 103 | if(!GetCmdArgIntEx(1, index)) { | 164 | if(!GetCmdArgIntEx(1, index)) { |
| 104 | ReplyToCommand(client, "Error: index argument not numerical"); | 165 | ReplyToCommand(client, "Error: index argument not numerical"); |
| 105 | return Plugin_Handled; | 166 | return Plugin_Handled; |
| @@ -119,23 +180,25 @@ public Action replacePattern(int client, int args) { | |||
| 119 | return Plugin_Handled; | 180 | return Plugin_Handled; |
| 120 | } | 181 | } |
| 121 | 182 | ||
| 122 | int index | 183 | int index; |
| 123 | if(!GetCmdArgIntEx(1, index)) { | 184 | if(!GetCmdArgIntEx(1, index)) { |
| 124 | ReplyToCommand(client, "Error: index argument not numerical"); | 185 | ReplyToCommand(client, "Error: index argument not numerical"); |
| 125 | return Plugin_Handled; | 186 | return Plugin_Handled; |
| 126 | } | 187 | } |
| 127 | 188 | ||
| 128 | char pattern[PATTERN_MAX_LEN]; | 189 | char pattern[PATTERN_MAX_LEN]; |
| 129 | GetCmdArg(2, pattern, sizeof(pattern)); | 190 | if(concatArgs(pattern, sizeof(pattern), PATTERN_MAX_LEN, args, 2) <= 0) { |
| 130 | // TODO: Error handling | 191 | ReplyToCommand(client, "Error: could not get argument list"); |
| 192 | return Plugin_Handled; | ||
| 193 | } | ||
| 131 | 194 | ||
| 132 | if(removePattern(index)) { | 195 | if(removePattern(index)) { |
| 133 | ReplyToCommand(client, "Error: could not remove pattern"); | 196 | ReplyToCommand(client, "Error: could not remove pattern"); |
| 134 | return Plugin_Handled; | 197 | return Plugin_Handled; |
| 135 | } | 198 | } |
| 136 | if(insertPattern(pattern, regexlist.Length - 1)) { | 199 | if(insertPattern(pattern, index)) { |
| 137 | ReplyToCommand(client, "Error: could not register pattern"); | 200 | ReplyToCommand(client, "Error: could not register pattern"); |
| 138 | return Plugin_Handled | 201 | return Plugin_Handled; |
| 139 | } | 202 | } |
| 140 | // Preferably this would be atomic as to not lose a pattern, but that's something I can do later | 203 | // Preferably this would be atomic as to not lose a pattern, but that's something I can do later |
| 141 | 204 | ||
| @@ -156,23 +219,25 @@ public Action listPatterns(int client, int args) { | |||
| 156 | 219 | ||
| 157 | 220 | ||
| 158 | int insertPattern(char pattern[PATTERN_MAX_LEN], int index) { | 221 | int insertPattern(char pattern[PATTERN_MAX_LEN], int index) { |
| 159 | if(IsNullString(pattern) || index < 0 || index >= regexlist.Length) return -1; | 222 | if(IsNullString(pattern) || index < 0 || index > regexlist.Length) return -1; |
| 160 | 223 | ||
| 161 | static char errstr[512]; static RegexError reerr; | 224 | char errstr[512]; RegexError reerr; |
| 162 | Regex res = CompileRegex(pattern, gcvarRegexCompFlags.IntValue, errstr, sizeof(errstr), reerr); | 225 | Regex res = CompileRegex(pattern, gcvarRegexCompFlags.IntValue, errstr, sizeof(errstr), reerr); |
| 163 | if(res == null) { | 226 | if(res == null) { |
| 164 | LogError("Error: Could not compile regex pattern \"%s\": %s (%d)", pattern, errstr, reerr); | 227 | LogError("Error: Could not compile regex pattern \"%s\": %s (%d)", pattern, errstr, reerr); |
| 165 | return -1; | 228 | return -1; |
| 166 | } | 229 | } |
| 167 | 230 | ||
| 168 | if(index != (regexlist.Length - 1)) { | 231 | if(index == regexlist.Length) { |
| 232 | regexlist.Push(res); | ||
| 233 | patternlist.Push(pattern); | ||
| 234 | |||
| 235 | } else { | ||
| 169 | regexlist.ShiftUp(index); | 236 | regexlist.ShiftUp(index); |
| 170 | patternlist.ShiftUp(index); | 237 | patternlist.ShiftUp(index); |
| 171 | regexlist.Set(index, res); | 238 | regexlist.Set(index, res); |
| 172 | patternlist.Set(index, pattern); | 239 | patternlist.Set(index, pattern); |
| 173 | } else { | 240 | |
| 174 | regexlist.Push(res); | ||
| 175 | patternlist.Push(pattern); | ||
| 176 | } | 241 | } |
| 177 | 242 | ||
| 178 | // TODO: This should also insert the pattern into the database | 243 | // TODO: This should also insert the pattern into the database |
| @@ -193,14 +258,15 @@ int removePattern(int index) { | |||
| 193 | 258 | ||
| 194 | 259 | ||
| 195 | 260 | ||
| 261 | // Check's a user's name against the regex list. Returns -1 on error, 0 if skipped, 1 on hit | ||
| 196 | int checkName(int client) { | 262 | int checkName(int client) { |
| 197 | if(client <= 0) return -1; | 263 | if(client <= 0) return 0; |
| 198 | if(gcvarOperMode.IntValue == view_as<int>(OP_DISABLED)) return -1; | 264 | if(gcvarOperMode.IntValue == view_as<int>(OP_DISABLED)) return 0; |
| 199 | if(CheckCommandAccess(client, "", gcvarAmdImmFlag.IntValue, true)) return -1; | 265 | if(CheckCommandAccess(client, "", gcvarAmdImmFlag.IntValue, true)) return 0; |
| 200 | 266 | ||
| 201 | char name[64 + 1]; | 267 | char name[64 + 1]; |
| 202 | if(getName(client, name, sizeof(name)) <= 0) { | 268 | if(getName(client, name, sizeof(name)) <= 0) { |
| 203 | LogError("Tried to get a client's name for a name check, but could not") | 269 | LogError("Tried to get a client's name for a name check, but could not"); |
| 204 | return -1; | 270 | return -1; |
| 205 | } | 271 | } |
| 206 | 272 | ||
| @@ -218,7 +284,7 @@ int checkName(int client) { | |||
| 218 | break; | 284 | break; |
| 219 | } | 285 | } |
| 220 | 286 | ||
| 221 | return 0; | 287 | return 1; |
| 222 | } | 288 | } |
| 223 | 289 | ||
| 224 | int getName(int client, char[] buf, int buflen) { | 290 | int getName(int client, char[] buf, int buflen) { |
| @@ -254,7 +320,7 @@ int handleNameHit(int client) { | |||
| 254 | } | 320 | } |
| 255 | 321 | ||
| 256 | int handleFailedRegex(int client, RegexError reerr) { | 322 | int handleFailedRegex(int client, RegexError reerr) { |
| 257 | static char regstr[128]; | 323 | char regstr[128]; |
| 258 | RegexStrError(reerr, regstr, sizeof(regstr)); | 324 | RegexStrError(reerr, regstr, sizeof(regstr)); |
| 259 | 325 | ||
| 260 | LogError("Ran into regex error when trying to check user %L's name. Reported regex error: %s", client, regstr); | 326 | LogError("Ran into regex error when trying to check user %L's name. Reported regex error: %s", client, regstr); |
| @@ -267,64 +333,62 @@ int handleFailedRegex(int client, RegexError reerr) { | |||
| 267 | int RegexStrError(RegexError err, char[] buf, int buflen) { | 333 | int RegexStrError(RegexError err, char[] buf, int buflen) { |
| 268 | if(IsNullString(buf)) return -1; | 334 | if(IsNullString(buf)) return -1; |
| 269 | 335 | ||
| 336 | char tmp[64]; | ||
| 270 | switch(err) { | 337 | switch(err) { |
| 271 | case REGEX_ERROR_NONE: {Format(buf, buflen, "No error");} /* No error */ | 338 | case REGEX_ERROR_NONE: {tmp = "No error";} |
| 272 | 339 | ||
| 273 | case REGEX_ERROR_ASSERT: {Format(buf, buflen, "Internal error");} | 340 | case REGEX_ERROR_ASSERT: {tmp = "Internal error";} |
| 274 | case REGEX_ERROR_BADBR: {Format(buf, buflen, "Invalid repeat counts in {}");} | 341 | case REGEX_ERROR_BADBR: {tmp = "Invalid repeat counts in {}";} |
| 275 | case REGEX_ERROR_BADPAT: {Format(buf, buflen, "Pattern error");} | 342 | case REGEX_ERROR_BADPAT: {tmp = "Pattern error";} |
| 276 | case REGEX_ERROR_BADRPT: {Format(buf, buflen, "? * + invalid");} | 343 | case REGEX_ERROR_BADRPT: {tmp = "? * + invalid";} |
| 277 | case REGEX_ERROR_EBRACE: {Format(buf, buflen, "Unbalanced {}");} | 344 | case REGEX_ERROR_EBRACE: {tmp = "Unbalanced {}";} |
| 278 | case REGEX_ERROR_EBRACK: {Format(buf, buflen, "Unbalanced []");} | 345 | case REGEX_ERROR_EBRACK: {tmp = "Unbalanced []";} |
| 279 | case REGEX_ERROR_ECOLLATE: {Format(buf, buflen, "Collation error - not relevant");} | 346 | case REGEX_ERROR_ECOLLATE: {tmp = "Collation error - not relevant";} |
| 280 | case REGEX_ERROR_ECTYPE: {Format(buf, buflen, "Bad class");} | 347 | case REGEX_ERROR_ECTYPE: {tmp = "Bad class";} |
| 281 | case REGEX_ERROR_EESCAPE: {Format(buf, buflen, "Bad escape sequence");} | 348 | case REGEX_ERROR_EESCAPE: {tmp = "Bad escape sequence";} |
| 282 | case REGEX_ERROR_EMPTY: {Format(buf, buflen, "Empty expression");} | 349 | case REGEX_ERROR_EMPTY: {tmp = "Empty expression";} |
| 283 | case REGEX_ERROR_EPAREN: {Format(buf, buflen, "Unbalanced ()");} | 350 | case REGEX_ERROR_EPAREN: {tmp = "Unbalanced ()";} |
| 284 | case REGEX_ERROR_ERANGE: {Format(buf, buflen, "Bad range inside []");} | 351 | case REGEX_ERROR_ERANGE: {tmp = "Bad range inside []";} |
| 285 | case REGEX_ERROR_ESIZE: {Format(buf, buflen, "Expression too big");} | 352 | case REGEX_ERROR_ESIZE: {tmp = "Expression too big";} |
| 286 | case REGEX_ERROR_ESPACE: {Format(buf, buflen, "Failed to get memory");} | 353 | case REGEX_ERROR_ESPACE: {tmp = "Failed to get memory";} |
| 287 | case REGEX_ERROR_ESUBREG: {Format(buf, buflen, "Bad back reference");} | 354 | case REGEX_ERROR_ESUBREG: {tmp = "Bad back reference";} |
| 288 | case REGEX_ERROR_INVARG: {Format(buf, buflen, "Bad argument");} | 355 | case REGEX_ERROR_INVARG: {tmp = "Bad argument";} |
| 289 | 356 | ||
| 290 | case REGEX_ERROR_NOMATCH: {Format(buf, buflen, "No match was found");} | 357 | case REGEX_ERROR_NOMATCH: {tmp = "No match was found";} |
| 291 | case REGEX_ERROR_NULL: {Format(buf, buflen, "Null");} | 358 | case REGEX_ERROR_NULL: {tmp = "Null";} |
| 292 | case REGEX_ERROR_BADOPTION: {Format(buf, buflen, "Bad Option");} | 359 | case REGEX_ERROR_BADOPTION: {tmp = "Bad Option";} |
| 293 | case REGEX_ERROR_BADMAGIC: {Format(buf, buflen, "Bad Magic");} | 360 | case REGEX_ERROR_BADMAGIC: {tmp = "Bad Magic";} |
| 294 | case REGEX_ERROR_UNKNOWN_OPCODE: {Format(buf, buflen, "Unknown OpCode");} | 361 | case REGEX_ERROR_UNKNOWN_OPCODE: {tmp = "Unknown OpCode";} |
| 295 | case REGEX_ERROR_NOMEMORY: {Format(buf, buflen, "No Memory");} | 362 | case REGEX_ERROR_NOMEMORY: {tmp = "No Memory";} |
| 296 | case REGEX_ERROR_NOSUBSTRING: {Format(buf, buflen, "No substring");} | 363 | case REGEX_ERROR_NOSUBSTRING: {tmp = "No substring";} |
| 297 | case REGEX_ERROR_MATCHLIMIT: {Format(buf, buflen, "Match limit");} | 364 | case REGEX_ERROR_MATCHLIMIT: {tmp = "Match limit";} |
| 298 | case REGEX_ERROR_CALLOUT: {Format(buf, buflen, "Callout");} // Never used by PCRE itself | 365 | case REGEX_ERROR_CALLOUT: {tmp = "Callout";} // Never used by PCRE itself |
| 299 | case REGEX_ERROR_BADUTF8: {Format(buf, buflen, "Bad UTF8");} | 366 | case REGEX_ERROR_BADUTF8: {tmp = "Bad UTF8";} |
| 300 | case REGEX_ERROR_BADUTF8_OFFSET: {Format(buf, buflen, "Bad UTF8 offset");} | 367 | case REGEX_ERROR_BADUTF8_OFFSET: {tmp = "Bad UTF8 offset";} |
| 301 | case REGEX_ERROR_PARTIAL: {Format(buf, buflen, "Partial");} | 368 | case REGEX_ERROR_PARTIAL: {tmp = "Partial";} |
| 302 | case REGEX_ERROR_BADPARTIAL: {Format(buf, buflen, "Bad Partial");} | 369 | case REGEX_ERROR_BADPARTIAL: {tmp = "Bad Partial";} |
| 303 | case REGEX_ERROR_INTERNAL: {Format(buf, buflen, "Internal error");} | 370 | case REGEX_ERROR_INTERNAL: {tmp = "Internal error";} |
| 304 | case REGEX_ERROR_BADCOUNT: {Format(buf, buflen, "Bad count");} | 371 | case REGEX_ERROR_BADCOUNT: {tmp = "Bad count";} |
| 305 | case REGEX_ERROR_DFA_UITEM: {Format(buf, buflen, "DFA UItem");} | 372 | case REGEX_ERROR_DFA_UITEM: {tmp = "DFA UItem";} |
| 306 | case REGEX_ERROR_DFA_UCOND: {Format(buf, buflen, "DFA UCOND");} | 373 | case REGEX_ERROR_DFA_UCOND: {tmp = "DFA UCOND";} |
| 307 | case REGEX_ERROR_DFA_UMLIMIT: {Format(buf, buflen, "DFA UMLIMIT");} | 374 | case REGEX_ERROR_DFA_UMLIMIT: {tmp = "DFA UMLIMIT";} |
| 308 | case REGEX_ERROR_DFA_WSSIZE: {Format(buf, buflen, "DFA WSSIZE");} | 375 | case REGEX_ERROR_DFA_WSSIZE: {tmp = "DFA WSSIZE";} |
| 309 | case REGEX_ERROR_DFA_RECURSE: {Format(buf, buflen, "DFA recurse");} | 376 | case REGEX_ERROR_DFA_RECURSE: {tmp = "DFA recurse";} |
| 310 | case REGEX_ERROR_RECURSIONLIMIT: {Format(buf, buflen, "Recursion Limit");} | 377 | case REGEX_ERROR_RECURSIONLIMIT: {tmp = "Recursion Limit";} |
| 311 | case REGEX_ERROR_NULLWSLIMIT: {Format(buf, buflen, "NULL WSLIMIT");} /* No longer actually used */ | 378 | case REGEX_ERROR_NULLWSLIMIT: {tmp = "NULL WSLIMIT";} /* No longer actually used */ |
| 312 | case REGEX_ERROR_BADNEWLINE: {Format(buf, buflen, "Bad newline");} | 379 | case REGEX_ERROR_BADNEWLINE: {tmp = "Bad newline";} |
| 313 | case REGEX_ERROR_BADOFFSET: {Format(buf, buflen, "Bad offset");} | 380 | case REGEX_ERROR_BADOFFSET: {tmp = "Bad offset";} |
| 314 | case REGEX_ERROR_SHORTUTF8: {Format(buf, buflen, "Short UFT8");} | 381 | case REGEX_ERROR_SHORTUTF8: {tmp = "Short UFT8";} |
| 315 | case REGEX_ERROR_RECURSELOOP: {Format(buf, buflen, "Recurse loop");} | 382 | case REGEX_ERROR_RECURSELOOP: {tmp = "Recurse loop";} |
| 316 | case REGEX_ERROR_JIT_STACKLIMIT: {Format(buf, buflen, "JIT Stacklimit");} | 383 | case REGEX_ERROR_JIT_STACKLIMIT: {tmp = "JIT Stacklimit";} |
| 317 | case REGEX_ERROR_BADMODE: {Format(buf, buflen, "Bad mode");} | 384 | case REGEX_ERROR_BADMODE: {tmp = "Bad mode";} |
| 318 | case REGEX_ERROR_BADENDIANNESS: {Format(buf, buflen, "Bad endianness");} | 385 | case REGEX_ERROR_BADENDIANNESS: {tmp = "Bad endianness";} |
| 319 | case REGEX_ERROR_DFA_BADRESTART: {Format(buf, buflen, "DFA Bad Restart");} | 386 | case REGEX_ERROR_DFA_BADRESTART: {tmp = "DFA Bad Restart";} |
| 320 | case REGEX_ERROR_JIT_BADOPTION: {Format(buf, buflen, "JIT bad option");} | 387 | case REGEX_ERROR_JIT_BADOPTION: {tmp = "JIT bad option";} |
| 321 | case REGEX_ERROR_BADLENGTH: {Format(buf, buflen, "Bad length");} | 388 | case REGEX_ERROR_BADLENGTH: {tmp = "Bad length";} |
| 322 | 389 | ||
| 323 | default: {Format(buf, buflen, "Unknown Error");} | 390 | default: {tmp = "Unknown Error";} |
| 324 | } | 391 | } |
| 325 | 392 | ||
| 326 | // Yeah I know this is terrible, and it's entirely because I'm not certain how string assignments work. If this were C I would | 393 | return strcopy(buf, buflen, tmp); |
| 327 | // make a normal char* string and make it point to different text depending on the case | ||
| 328 | |||
| 329 | return 0; | ||
| 330 | } \ No newline at end of file | 394 | } \ No newline at end of file |
