#include #include #include int digitValue(int c) { switch (c) { case '0'...'9': return c - '0'; case 'A'...'Z': return c - 'A' + 10; case 'a'...'z': return c - 'a' + 10; } return 666; } int isRadix(int r, int c) { return digitValue(c) < r; } int unescapedCharacter(char *cp, char **ep) { int c= 0; c= *cp++; if ('\\' == c) { c= *cp++; switch (c) { case 'n': c= 10; break; case 'a': c= 7; break; case 'b': c= 8; break; case 'e': c= 27; break; case 'f': c= 12; break; case 'r': c= 13; break; case 't': c= 9; break; case 'v': c= 1; break; case '\\': c= '\\'; break; case ']': c= ']'; break; case '-': c= '-'; break; case '0'...'7': { c -= '0'; // c is now the value of the digit that represented it if (isRadix(8, *cp)) c= c * 8 + *cp++ - '0'; if (isRadix(8, *cp)) c= c * 8 + *cp++ - '0'; break; } case 'x': { char *op= cp; c= 0; if (isRadix(16, *cp)) { c= c * 16 + digitValue(*cp++); if (isRadix(16, *cp)) { c= c * 16 + digitValue(*cp++); break; } } fprintf(stderr, "illegal hexadecimal escape: \\x%.2s\n", op); break; } default: fprintf(stderr, "unusual escape: \\%c\n", c); break; } } if (ep) *ep= cp; return c; } char *classify(char *spec) { char *class= calloc(1, 32); int negated= 0; if ('^' == *spec) ++negated, ++spec; int prevChar= 0; while (*spec) { if ('-' == *spec && prevChar && spec[1]) { ++spec; int thisChar= unescapedCharacter(spec, &spec); if (thisChar < prevChar) { fprintf(stderr, "range is backwards: \\x%x-\\x%x\n", prevChar, thisChar); int tmp= prevChar; prevChar= thisChar; thisChar= tmp; } for (int i= prevChar; i <= thisChar; ++i) setBit(class, i); prevChar= 0; continue; } prevChar= *spec; setBit(class, unescapedCharacter(spec, &spec)); } if (negated) for (int i= 0; i < 32; ++i) class[i] ^= 255; // invert all bits in the class return class; } #ifdef TESTING_CLASS_C int main() { char *line=0; size_t line_max=0; ssize_t line_len=0; char a='a'; printf("%i\n",(int)a); printf("%s",classify("a")); while ((line_len= getline(&line,&line_max,stdin)) >= 0) { if (line_len>0 && line[line_len-1]=='\n') { line[line_len-1]=0; } char *class= classify(line); for (int i= 0; i < 256; ++i) if (testBit(class, i)) printf("%02x is set\n", i); } return 0; } #endif