#include <stdio.h>
#define QUOTE_COLOR "#ff0000"
#define COMMENT_COLOR "#408080"
char *Reserved_Words[] = {
"ACCESS", "ELSEIF", "PUBLIC",
"ADD", "END", "RAISE",
"ALL", "ENTRY", "RANGE",
"ALTER", "EXCEPTION", "REAL",
"AND", "EXCEPTION_INIT", "RECORD",
"ANY", "EXISTS", "RELEASE",
"ARRAY", "EXIT", "REM",
"ARRAYLEN", "FALSE", "RENAME",
"AS", "FETCH", "RESOURCE",
"ASC", "FLOAT", "RETURN",
"ASSERT", "FOR", "REVERSE",
"ASSIGN", "FORM", "REVOKE",
"AT", "FORMAT", "ROLLBACK",
"AUTHORIZATION", "FROM", "ROWID",
"BASE_TABLE", "FUNCTION", "ROWLABEL",
"BEGIN", "GENERIC", "ROWNUM",
"BETWEEN", "GOTO", "ROWTYPE",
"BINARY_INTEGER", "GRANT", "RUN",
"BODY", "GROUP", "SAVEPOINT",
"BOOLEAN", "HAVING", "SCHEMA",
"BY", "IDENTIFIED", "SELECT",
"CASE", "IF", "SEPARATE",
"CHAR", "IN", "SET",
"CHAR_BASE", "INDEX", "SIZE",
"CHECK", "INDEXES", "SMALLINT",
"CLOSE", "INDICATOR", "SPACE",
"CLUSTER", "INSERT", "SPOOL",
"CLUSTERS", "INTEGER", "SQL",
"COLAUTH", "INTERSECT", "SQLCODE",
"COLUMN", "INTO", "SQLERRM",
"COLUMNS", "IS", "START",
"COMMIT", "LEVEL", "STATEMENT",
"COMPRESS", "LIKE", "SUBTYPE",
"CONNECT", "LIMITED", "TABAUTH",
"CONSTANT", "LOOP", "TABLE",
"CRASH", "MINUS", "TABLES",
"CREATE", "MLSLABEL", "TABLESPACE",
"CURRENT", "NATURAL", "TASK",
"CURRVAL", "NEW", "TERMINATE",
"CURSOR", "NEXTVAL", "THEN",
"DATA_BASE", "NOCOMPRESS", "TO",
"DATABASE", "NOT", "TRUE",
"DATE", "NULL", "TYPE",
"DBA", "NUMBER", "UNFORMAT",
"DEBUGOFF", "NUMBER_BASE", "UNION",
"DEBUGON", "OF", "UNIQUE",
"DECIMAL", "ON", "UPDATE",
"DECLARE", "OPEN", "USE",
"DEFAULT", "OPTION", "VALUES",
"DEFINITION", "OR", "VARCHAR",
"DELAY", "ORDER", "VARCHAR2",
"DELETE", "OTHERS", "VIEW",
"DELTA", "OUT", "VIEWS",
"DESC", "PACKAGE", "WHEN",
"DIGITS", "PARTITION", "WHERE",
"DISPOSE", "PCTFREE", "WHILE",
"DISTINCT", "POSITIVE", "WITH",
"DO", "PRAGMA", "WORK",
"DROP", "PRIOR", "XOR",
/* Additions by GT: */
"REPLACE", "PROCEDURE", "ELSE",
"ELSIF", "PLS_INTEGER", "ROWCOUNT",
"ISOPEN", "FORALL",
NULL
};
int IsReservedWord(char *word)
{
int i = 0;
char *s = word;
for (;;) {
if (Reserved_Words[i] == NULL) break;
if (!strcasecmp(word, Reserved_Words[i++])) return 1;
}
#ifdef UC_HACK
while (*s != '\0') {
if ((isalpha(*s)) && (!isupper(*s))) return 0;
s += 1;
}
return 1;
#else
return 0;
#endif
}
int main(int argc, char **argv)
{
#define NEXTCH {c = fgetc(stdin); \
pend = fgetc(stdin); \
ungetc(pend, stdin); \
}
// surface-level line reconstruction on PL/SQL source,
// no deep parsing. Used for conversion to HTML with
// 'syntax colouring' (actually lexical colouring)
int c = -1, pend = -1, lastch;
// start of html
printf("<html><head><title></title></head><body><PRE>");
for (;;) {
lastch = c;
NEXTCH; // C is always the current character, pend is what you will read next.
if (c == EOF) {
// end of html
break;
} else if (lastch == '\n' && c == '/' && pend == '\n') {
printf("<HR>\n");
} else if (c == '/' && pend == '*') {
// handle C comment
printf("<font color=%s><i>/*", COMMENT_COLOR);
NEXTCH; // C is '*'
for (;;) {
NEXTCH;
if (c == '*' && pend == '/') break;
putchar(c);
}
NEXTCH; // skip /
printf("*/</i></font>");
} else if (c == '/' && pend == '/') {
// handle C++ comment
printf("<font color=%s><i>/", COMMENT_COLOR);
for (;;) {
if (c == '\n') break;
putchar(c);
NEXTCH
}
printf("</i></font>\n");
} else if (c == '-' && pend == '-') {
// handle ADA comment
printf("<font color=%s><i>", COMMENT_COLOR);
for (;;) {
if (c == '\n') break;
putchar(c);
NEXTCH
}
printf("</i></font>\n");
} else if (c == '\'') {
// handle squote literal
printf("<font color=%s>'", QUOTE_COLOR);
for (;;) {
NEXTCH; // how are single quotes escaped in PL/SQL?
// - I think by doubling, so fix this!
putchar(c);
if (c == '\'') break;
}
printf("</font>");
} else if (c == '"') {
// handle dquote literal
printf("<font color=%s>\"", QUOTE_COLOR);
for (;;) {
NEXTCH; // how are double quotes escaped in PL/SQL?
// - I think by doubling, so fix this!
putchar(c);
if (c == '"') break;
}
printf("</font>");
} else if (isdigit(c)) {
// handle number
// for now, leave untouched.
//printf("<font color=%s><i>\"", NUMBER_COLOR);
putchar(c);
for (;;) {
if (!isdigit(pend)) break;
NEXTCH; // How about reals, exponents etc?
putchar(c);
}
//printf("</i></font>");
} else if (isalpha(c)) {
// handle keyword or variable
char words[1024];
char *word = words;
for (;;) {
*word++ = c;
if (!(isalpha(pend) || isdigit(pend) || (pend == '_') || (pend == '#'))) break;
NEXTCH; // What non-std chars are allowed? #? .? _?
}
*word = '\0';
if (lastch != '.' && IsReservedWord(words)) {
printf("<b>%s</b>", words);
} else {
printf("%s", words);
}
} else if (c == '&') {
printf("&");
} else if (c == '<') {
printf("<");
} else if (c == '>') {
printf(">");
} else if (c == '\n') {
printf("\n");
} else {
// output noise char
putchar(c);
}
}
printf("</PRE></body></html>\n");
}