/* keywords.c */ #include #include typedef enum {false, true} bool; #define TAB 9 #define loop while(1) #ifdef UNIX # include # define clear_memory(p, n) memset(p, 0, n) #endif #define USAGE "keywords input-file [-o output-file]" static void error(int number, char *message) { fprintf(stderr, "keywords: *** error #%d *** %s\n", number, message); exit(1); } static void usage(void) { fprintf(stderr, "keywords usage: %s\n", USAGE); exit(1); } static FILE *in, *out; static unsigned char *in_buffer, *out_buffer, ch; static long in_size, out_size, in_pos, out_pos; static bool next_ch(void) { if (++in_pos >= in_size) { ch = ' '; return false; } ch = in_buffer[in_pos]; if (ch == TAB) out_buffer[out_pos++] = ' '; else out_buffer[out_pos++] = ch; return true; } static unsigned char look_ahead(long n) { return in_buffer[in_pos + n]; } static void skip_to(unsigned char stop) { while (ch != stop && next_ch()); } static void skip_comment(void) { long level; level = 1; next_ch(); while (next_ch()) { if (ch == '*' && look_ahead(1) == ')') { next_ch(); if (--level <= 0) return; } else if (ch == '(' && look_ahead(1) == '*') { next_ch(); level++; } } error(8, "*) missing"); } static bool letter[256]; static long word_length(void) { long i; i = in_pos; while (letter[in_buffer[i]]) i++; return i - in_pos; } static bool found(long n, char *s) { return strncmp(&in_buffer[in_pos], s, n) == 0 && strlen(s) == n; } static bool keyword(long n) { return (found(n, "and") || found(n, "andif") || found(n, "begin") || found(n, "case") || found(n, "do") || found(n, "downto") || found(n, "else") || found(n, "elsif") || found(n, "end") || found(n, "exception") || found(n, "exit") || found(n, "export") || found(n, "extend") || found(n, "for") || found(n, "fun") || found(n, "hide") || found(n, "if") || found(n, "import") || found(n, "in") || found(n, "interface") || found(n, "let") || found(n, "library") || found(n, "loop") || found(n, "module") || found(n, "of") || found(n, "ok") || found(n, "open") || found(n, "orif") || found(n, "raise") || found(n, "reraise") || found(n, "rec") || found(n, "then") || found(n, "try") || found(n, "tuple") || found(n, "typecase") || found(n, "upto") || found(n, "var") || found(n, "when") || found(n, "while") || found(n, "with") || found(n, "Dyn") || found(n, "Exception") || found(n, "Fun") || found(n, "Let") || found(n, "Nok") || found(n, "Ok") || found(n, "Oper") || found(n, "Rec") || found(n, "Repeat") || found(n, "Tuple")); } static void put_ch(unsigned char ch) { out_buffer[out_pos++] = ch; } static void perform(void) { long n, i; while (next_ch()) { if (ch == '(' && look_ahead(1) == '*') skip_comment(); else if (ch == '\\' && found(13, "\\begin{cxple}")) { skip_to('}'); loop { if (!next_ch()) error(3, "\\end{cxple} missing"); if (ch == '_' || ch == '{' || ch == '}') { in_pos--; out_pos--; put_ch('\\'); next_ch(); } else if (ch == '\\') { if (found(11, "\\end{cxple}")) break; else { next_ch(); if (ch == '_' || ch == '{' || ch == '}') next_ch(); else { while (letter[ch]) next_ch(); if (ch == '{') skip_to('}'); } } } } } else if (ch == '\\' && found(12, "\\begin{xple}")) { skip_to('}'); loop { if (!next_ch()) error(3, "\\end{xple} missing"); if (ch == '(' && in_buffer[in_pos + 1] == '*') skip_comment(); else if (ch == '`' && look_ahead(1) == '`') /* skip string */ { do next_ch(); while (ch != '\'' && look_ahead(1) != '\''); } else if (ch == '\\') { if (look_ahead(1) == 'k' && look_ahead(2) == '{') skip_to('}'); else if (found(10, "\\end{xple}")) break; else { next_ch(); while (letter[ch]) next_ch(); if (ch == '{') skip_to('}'); } } else if (letter[ch]) { n = word_length(); if (!keyword(n)) for (i = 1; i < n; i++) next_ch(); else { in_pos--; out_pos--; put_ch('\\'); put_ch('k'); put_ch('{'); for (i = 1; i <= n; i++) next_ch(); put_ch('}'); } } } } } } static long file_size(FILE *file) { if (fseek(file, 0, 2) != 0) error(3, "fseek failed"); return ftell(file); } static void init(void) { unsigned char i; clear_memory(letter, 256); for (i = 'A'; i <= 'Z'; i++) letter[i] = true; for (i = 'a'; i <= 'z'; i++) letter[i] = true; for (i = '0'; i <= '9'; i++) letter[i] = true; } int main(int argc, char *argv[]) { char *input_filename = 0; char *output_filename = 0; int i; if (argc < 2) usage(); i = 1; while (i < argc) { if (strcmp(argv[i], "-o") == 0) { if (output_filename || i >= argc) usage(); output_filename = argv[++i]; } else { if (input_filename) usage(); input_filename = argv[i]; } i++; } init(); if (!input_filename) usage(); in = fopen(input_filename, "r"); if (in == NULL) error(1, "input file could not be opened."); in_size = file_size(in); in_buffer = (unsigned char *) malloc(in_size + 100); if (!in_buffer) error(4, "input buffer allocation failed"); clear_memory(in_buffer, in_size + 100); out_size = in_size * 2; out_buffer = (unsigned char *) malloc(out_size); if (!out_buffer) error(4, "output buffer allocation failed"); if (fseek(in, 0, 0) != 0) error(3, "fseek failed"); if (fread(in_buffer, 1, in_size, in) != in_size) error(5, "read failed"); fclose(in); ch = ' '; in_pos = -1; out_pos = 0; perform(); if (!output_filename) out = stdout; else { out = fopen(output_filename, "w"); if (out == NULL) error(2, "output file could not be opened."); } if (fwrite(out_buffer, 1, out_pos, out) != out_pos) error(6, "write failed"); fclose(out); free(in_buffer); free(out_buffer); exit(0); return 0; }