#include #include "token.h" //-------- First we define token dl-list members ----------------// token* curr_token; token token::dummy(CAT_SPEC, TKN_DUMMY); // Initialize token DL-ring char* const token::token_name[] = { #define DEF_TOKEN(m_text, m_cat, m_tag, m_keyword) \ m_text, #include "token.dpp" }; int const token::token_cat[] = { #define DEF_TOKEN(m_text, m_cat, m_tag, m_keyword) \ CAT_##m_cat, #include "token.dpp" }; token::token(token& t) { *this = t; clone = NULL; t.clone = this; if (bind != NULL) bind = bind->clone; } void token::remove() { prev ->next = next; next->prev = prev; } token* token::next_relevant() { token* t; for (t = next; t->cat == CAT_WSPC; t = t->next); return t; } token* token::prev_relevant() { token* t; for (t = prev; t->cat == CAT_WSPC; t = t->prev); return t; } token* token::first_relevant() { return dummy.next_relevant(); } token* token::last_relevant() { return dummy.prev_relevant(); } void token::remove(token* head, token* tail) { head->prev->next = tail->next; tail->next->prev = head->prev; } void token::disable(token* head, token* tail) { while(TRUE) { if (head->tag != TKN_CMNT && head->tag != TKN_LN) { head->disable(); } if (head == tail) break; head = head->next; } } void token::disappear() { token* t = this; do { t->disable(); t = t->next; } while (t->tag == TKN_SPACE || t->tag == TKN_LN); } token* token::get_first_token() { token *t; for (t = this; t->tag != TKN_LN && t->tag != TKN_DUMMY; t = t->prev); return t->next_relevant(); } token* token::copy(token* head, token* tail) { token* first = head; while (TRUE) { (new token(*head))->insert_b(this); if (head == tail) break; head = head->next; } first->clone->pos = pos; return first->clone; } void token::swap(token* left_head, token* left_tail, token* right_head, token* right_tail) { token* t; left_head->prev->next = right_head; left_tail->next->prev = right_tail; right_head->prev->next = left_head; right_tail->next->prev = left_tail; t = right_head->prev; right_head->prev = left_head->prev; left_head->prev = t; t = right_tail->next; right_tail->next = left_tail->next; left_tail->next = t; } token* token::move(token* head, token* tail) { head->prev->next = tail->next; tail->next->prev = head->prev; tail->next = this; head->prev = prev; prev->next = head; prev = tail; head->pos = pos; return head; } token* token::move_region(token* head, token* tail) { while (head->prev->cat == CAT_WSPC) { head = head->prev; } while (tail->next->cat == CAT_WSPC && tail->next->tag != TKN_LN) { tail = tail->next; } return move(head, tail); } //------------------------------------------------------------------------// void token::input(char *file) { scanner_input(file); while (yylex() > 0) curr_token->insert_b (&dummy); curr_token = NULL; } output_context::output_context(char* file) { f = fopen(file, "w"); if (f == NULL) { fprintf(stderr, "Can't open output source file: %s\n", file); exit(1); } pos = line = 0; prev_tag = TKN_LN; } output_context::~output_context() { if (f != NULL) fclose(f); } void output_context::output(token* t) { static int shift = 0; int t_pos; if (t->tag == TKN_BEG_SHIFT) { shift = -t->pos; return; } else if (t->tag == TKN_END_SHIFT) { shift = 0; return; } t_pos = t->bind ? t->bind->pos : t->pos + shift; if (t->out_text == NULL || (t->tag == TKN_SPACE && prev_tag == TKN_LN)) { return; } if (t_pos > pos && t->tag != TKN_LN && ((t->attr & token::fix_pos) || t->tag == TKN_CMNT || prev_tag == TKN_LN)) { // // Set token to specified position // while (pos < t_pos) { pos += 1; putc(' ', f); } } t->pos = pos; // // Separate output '>' symbols // if (*t->out_text == '>' && prev_tag == TKN_GT) { pos += 1; putc(' ', f); } // // Ignoring starting (trailing) spaces in generated tokens // if there are space tokens before (after) generated token // char* out = t->out_text; int len = strlen(out); if (t->cat == CAT_GEN) { if (out[0] == ' ' && (prev_tag == TKN_SPACE || prev_tag == TKN_LN)) { out += 1; len -= 1; } if (out[len-1] == ' ' && t->next->tag == TKN_SPACE) { len -= 1; } } // // Output text // prev_tag = t->tag; while (-- len >= 0) { switch(*out) { case '\n': pos = 0; line += 1; prev_tag = TKN_LN; break; case '\t': pos += TAB_WIDTH - (pos % TAB_WIDTH); prev_tag = TKN_SPACE; break; case ' ': prev_tag = TKN_SPACE; pos += 1; break; case '>': prev_tag = TKN_GT; pos += 1; break; default: pos += 1; prev_tag = t->tag; } putc(*out++, f); } } extern bool output_not_existed_hdr; static token* print_rec (char *file, token *t, bool unit_spec) { output_context ctx(file); char *ip1, *ip2; char *inc_file = NULL; FILE* f; token* nt; int tag; bool def_vars = FALSE; bool interface_module = FALSE; int file_name_len = 0; printf ("Output file %s\n", file); if (t->prev->tag == TKN_DUMMY) { fputs("#include \"ptoc.h\"\n\n", ctx.file()); } else if (unit_spec) { file_name_len = strrchr(file, '.') - file; fprintf(ctx.file(), "#ifndef __%.*s_h__\n#define __%.*s_h__\n", file_name_len, file, file_name_len, file); if (use_namespaces) { fprintf(ctx.file(), "namespace %.*s {\n", file_name_len, file); } interface_module = TRUE; } for (; (tag = t->tag) != TKN_DUMMY; t = t->next) { switch (tag) { case TKN_INTERFACE: ip1 = strrchr(file, '.'); inc_file = ip1 ? dprintf("%.*s.h", ip1 - file, file) : dprintf("%s.h", inc_file, file); fprintf(ctx.file(), "#include \"%s\"\n", inc_file); t = print_rec(inc_file, t->next, TRUE); continue; case TKN_PUSH_FILE: case TKN_PUSH_UNIT: ip1 = strrchr(t->in_text, '.'); ip2 = strrchr(t->out_text, '.'); assert (ip1 != NULL && ip2 != NULL); def_vars = FALSE; if (extern_vars && !turbo_pascal && strcmp(ip2, ".var") == 0 && strncmp(t->out_text, file, ip2-t->out_text+1) == 0) { def_vars = TRUE; } if (strcmp(ip1, ".pas") == 0) { strcpy(ip1, ".h"); strcpy(ip2, ".h"); } else { *ip1 = '_'; *ip2 = '_'; strcat(ip1, ".h"); strcat(ip2, ".h"); } if (tag == TKN_PUSH_UNIT) { fprintf(ctx.file(), "#include \"%s\"\n", t->out_text); } else { fprintf(ctx.file(), "#include \"%s\"", t->out_text); } inc_file = t->in_text; f = NULL; if (tag == TKN_PUSH_UNIT || (output_not_existed_hdr && (f = fopen(inc_file, "r")) != NULL)) { int nested = 1; if (f) fclose(f); do { t = t->next; if (t->tag == TKN_POP_FILE) nested -= 1; if (t->tag == TKN_PUSH_FILE) nested += 1; if (t->tag == TKN_PUSH_UNIT) nested += 1; if (t->tag == TKN_UNIT_END) nested -= 1; } while(nested); } else { t = print_rec(inc_file, t->next, FALSE); } if (tag != TKN_PUSH_UNIT) { for (nt = t->next; nt != NULL && nt->cat == CAT_WSPC && (nt->tag == TKN_SPACE || nt->tag == TKN_CMNT); nt = nt->next); if (nt && nt->tag != TKN_LN) { fputc('\n', ctx.file()); } } continue; case TKN_IMPLEMENTATION: case TKN_UNIT_END: case TKN_POP_FILE: if (interface_module) { if (use_namespaces) { fprintf(ctx.file(), "}\nusing namespace %.*s;\n", file_name_len, file); } fprintf(ctx.file(), "#endif\n"); } return t; default: ctx.output(t); } } return NULL; // end of main file } void token::output (char *file) { print_rec(file, dummy.next, FALSE); }