static int get_next_char() { int c, nxt; c = fileGetc(); if (c == EOF) return c; nxt = fileGetc(); if (nxt == EOF) return c; fileUngetc(nxt); if (c == '-' && nxt == '-') { skip_rest_of_line(); return get_next_char(); } if (c == '{' && nxt == '-') { int last = '\0'; do { last = c; c = get_next_char(); } while (! (c == EOF || (last == '-' && c == '}'))); return get_next_char(); } return c; }
static vString *parseNumeric (int c) { static vString *string = NULL; if (string == NULL) string = vStringNew (); vStringCopy (string, parseInteger (c)); c = fileGetc (); if (c == '.') { vStringPut (string, c); vStringCat (string, parseInteger ('\0')); c = fileGetc (); } if (tolower (c) == 'e') { vStringPut (string, c); vStringCat (string, parseInteger ('\0')); } else if (!isspace (c)) fileUngetc (c); vStringTerminate (string); return string; }
static int vGetc (void) { int c; if (Ungetc == '\0') c = fileGetc (); else { c = Ungetc; Ungetc = '\0'; } if (c == '-') { int c2 = fileGetc (); if (c2 == EOF) longjmp (Exception, (int) ExceptionEOF); else if (c2 == '-') /* strip comment until end-of-line */ { do c = fileGetc (); while (c != '\n' && c != EOF); } else Ungetc = c2; } if (c == EOF) longjmp (Exception, (int) ExceptionEOF); return c; }
/* If a numeric is passed in 'c', this is used as the first digit of the * numeric being parsed. */ static vString *parseInteger (int c) { static vString *string = NULL; if (string == NULL) string = vStringNew (); vStringClear (string); if (c == '\0') c = fileGetc (); if (c == '-') { vStringPut (string, c); c = fileGetc (); } else if (! isdigit (c)) c = fileGetc (); while (c != EOF && (isdigit (c) || c == '_')) { vStringPut (string, c); c = fileGetc (); } vStringTerminate (string); fileUngetc (c); return string; }
static void parseRegExp (void) { int c; boolean in_range = FALSE; do { c = fileGetc (); if (! in_range && c == '/') { do /* skip flags */ { c = fileGetc (); } while (isalpha (c)); fileUngetc (c); break; } else if (c == '\\') c = fileGetc (); /* skip next character */ else if (c == '[') in_range = TRUE; else if (c == ']') in_range = FALSE; } while (c != EOF); }
static int nextChar (void) { int c = fileGetc (); if (c == '\\') { c = fileGetc (); if (c == '\n') c = nextChar (); } return c; }
static int parseEscapedCharacter (void) { int d = '\0'; int c = fileGetc (); switch (c) { case 'A': d = '@'; break; case 'B': d = '\b'; break; case 'C': d = '^'; break; case 'D': d = '$'; break; case 'F': d = '\f'; break; case 'H': d = '\\'; break; case 'L': d = '~'; break; case 'N': d = '\n'; break; #ifdef QDOS case 'Q': d = 0x9F; break; #else case 'Q': d = '`'; break; #endif case 'R': d = '\r'; break; case 'S': d = '#'; break; case 'T': d = '\t'; break; case 'U': d = '\0'; break; case 'V': d = '|'; break; case '%': d = '%'; break; case '\'': d = '\''; break; case '"': d = '"'; break; case '(': d = '['; break; case ')': d = ']'; break; case '<': d = '{'; break; case '>': d = '}'; break; case '\n': skipToCharacter ('%'); break; case '/': { vString *string = parseInteger ('\0'); const char *value = vStringValue (string); const unsigned long ascii = atol (value); vStringDelete (string); c = fileGetc (); if (c == '/' && ascii < 256) d = ascii; break; } default: break; } return d; }
static int parseCharacter (void) { int c = fileGetc (); int result = c; if (c == '%') result = parseEscapedCharacter (); c = fileGetc (); if (c != '\'') skipToCharacter ('\n'); return result; }
static void skip_rest_of_line() { int c; do { c = fileGetc(); } while (c != EOF && c != '\n'); }
static int skipToCharacter (const int c) { int d; do { d = fileGetc (); } while (d != EOF && d != c); return d; }
static int get_token(char *token, int n) { int c = fileGetc(); int i = n; while (c != EOF && isident(c) && i < 1000) { token[i] = c; i++; c = fileGetc(); } if (c == EOF) return 0; if (i != n) { token[i] = '\0'; fileUngetc(c); return 1; } else { return 0; } }
static void parseTemplateString (vString *const string) { int c; do { c = fileGetc (); if (c == '`') break; vStringPut (string, c); if (c == '\\') { c = fileGetc(); vStringPut(string, c); } else if (c == '$') { c = fileGetc (); if (c != '{') fileUngetc (c); else { int depth = 1; /* we need to use the real token machinery to handle strings, * comments, regexes and whatnot */ tokenInfo *token = newToken (); LastTokenType = TOKEN_UNDEFINED; vStringPut(string, c); do { readTokenFull (token, FALSE, string); if (isType (token, TOKEN_OPEN_CURLY)) depth++; else if (isType (token, TOKEN_CLOSE_CURLY)) depth--; } while (! isType (token, TOKEN_EOF) && depth > 0); deleteToken (token); } } } while (c != EOF); vStringTerminate (string); }
static int vGetc (void) { int c; if (Ungetc == '\0') c = fileGetc (); else { c = Ungetc; Ungetc = '\0'; } if (c == '/') { int c2 = fileGetc (); if (c2 == EOF) longjmp (Exception, (int) ExceptionEOF); else if (c2 == '/') /* strip comment until end-of-line */ { do c = fileGetc (); while (c != '\n' && c != EOF); } else if (c2 == '*') /* strip block comment */ { c = skipOverCComment(); } else { fileUngetc (c2); } } else if (c == '"') /* strip string contents */ { int c2; do c2 = fileGetc (); while (c2 != '"' && c2 != EOF); c = '@'; } if (c == EOF) longjmp (Exception, (int) ExceptionEOF); return c; }
static void parseString (vString * const string, const int delimiter) { boolean end = FALSE; while (!end) { int c = fileGetc (); if (c == EOF) end = TRUE; else if (c == '\\') { c = fileGetc (); /* This maybe a ' or ". */ vStringPut (string, c); } else if (c == delimiter) end = TRUE; else vStringPut (string, c); } vStringTerminate (string); }
static void parseIdentifier (vString *const string, const int firstChar) { int c = firstChar; do { vStringPut (string, c); c = fileGetc (); } while (isIdentChar (c)); vStringTerminate (string); fileUngetc (c); /* always unget, LF might add a semicolon */ }
static void parseSelector (vString *const string, const int firstChar) { int c = firstChar; do { vStringPut (string, (char) c); c = fileGetc (); } while (isSelectorChar (c)); fileUngetc (c); vStringTerminate (string); }
static int get_line(char *buf) { int i = 0; int c; do { c = fileGetc(); buf[i++] = c; } while (c != EOF && c != '\n' && i < 1000); buf[i] = '\0'; return i; }
static void parseString (vString *const string, const int delimiter) { boolean end = FALSE; while (! end) { int c = fileGetc (); if (c == EOF) end = TRUE; else if (c == '\\') { /* Eat the escape sequence (\", \', etc). We properly handle * <LineContinuation> by eating a whole \<CR><LF> not to see <LF> * as an unescaped character, which is invalid and handled below. * Also, handle the fact that <LineContinuation> produces an empty * sequence. * See ECMA-262 7.8.4 */ c = fileGetc(); if (c != '\r' && c != '\n') vStringPut(string, c); else if (c == '\r') { c = fileGetc(); if (c != '\n') fileUngetc (c); } } else if (c == delimiter) end = TRUE; else if (c == '\r' || c == '\n') { /* those are invalid when not escaped */ end = TRUE; /* we don't want to eat the newline itself to let the automatic * semicolon insertion code kick in */ fileUngetc (c); } else vStringPut (string, c); } vStringTerminate (string); }
/* Read a C identifier beginning with "firstChar" and places it into * "name". */ static void parseIdentifier (vString *const string, const int firstChar) { int c = firstChar; Assert (isIdentChar (c)); do { vStringPut (string, c); c = fileGetc (); } while (isIdentChar (c)); vStringTerminate (string); fileUngetc (c); /* unget non-identifier character */ }
static void parseString (vString *const string, const int delimiter) { boolean end = FALSE; while (!end) { int c = fileGetc (); if (c == EOF) end = TRUE; else if (c == '\\' && delimiter != '`') { c = fileGetc (); if (c != '\'' && c != '\"') vStringPut (string, '\\'); vStringPut (string, c); } else if (c == delimiter) end = TRUE; else vStringPut (string, c); } vStringTerminate (string); }
static void parseFreeOperator (vString *const string, const int firstChar) { int c = firstChar; do { vStringPut (string, c); c = fileGetc (); } while (c > ' '); vStringTerminate (string); if (!isspace (c)) fileUngetc (c); /* unget non-identifier character */ }
static void parseString (vString *const string, const int delimiter) { boolean end = FALSE; int c; while (! end) { c = fileGetc (); if (c == EOF) end = TRUE; else if (c == delimiter) end = TRUE; else vStringPut (string, c); } vStringTerminate (string); }
static int vGetc (void) { int c; if (Ungetc == '\0') c = fileGetc (); else { c = Ungetc; Ungetc = '\0'; } if (c == '/') { int c2 = fileGetc (); if (c2 == EOF) longjmp (Exception, (int) ExceptionEOF); else if (c2 == '/') /* strip comment until end-of-line */ { do c = fileGetc (); while (c != '\n' && c != EOF); } else if (c2 == '*') /* strip block comment */ { do { do c = fileGetc (); while (c != '*' && c != EOF); if (c != EOF) c = fileGetc (); } while (c != '/' && c != EOF); if (c != EOF) c = ' '; /* comment equivalent to white space */ } else Ungetc = c2; } else if (c == '"') /* strip string contents */ { int c2; do c2 = fileGetc (); while (c2 != '"' && c2 != EOF); c = '@'; } if (c == EOF) longjmp (Exception, (int) ExceptionEOF); return c; }
static int inside_datatype(vString *name) { enum Find_State st = Find_Eq; int c; char token[1001]; while (1) { if (st == Find_Eq) { do { c = get_next_char(); if (c == '\n') { c = get_next_char(); if (! (c == ' ' || c == '\t')) { return c; } } } while (c != '='); st = Find_Constr; } else if (st == Find_Constr) { do { c = get_next_char(); } while (isspace(c)); if (!isupper(c)) { skip_rest_of_line(); return '\n'; } token[0] = c; if (!get_token(token, 1)) return '\n'; add_tag(token, K_CONSTRUCTOR, name); st = Find_Extr; } else if (st == Find_Extr) { c = get_next_char(); if (c == '{') st = Get_Extr; else if (c == '|') st = Find_Constr; else if (c == '\n') { c = get_next_char(); if (! (c == ' ' || c == '\t')) { return c; } } else if (!isspace(c)) st = Find_Bar; } else if (st == Get_Extr) { do { c = fileGetc(); } while (isspace(c)); if (c == EOF) return c; token[0] = c; get_token(token, 1); add_tag(token, K_FUNCTION, name); do { c = get_next_char(); if (c == '}') { st = Find_Bar; break; } } while (c != ','); } else if (st == Find_Bar) { do { c = get_next_char(); if (c == '\n') { c = get_next_char(); if (! (c == ' ' || c == '\t')) { return c; } } } while (c != EOF && c != '|'); st = Find_Constr; } } return '\n'; }
static void readToken (tokenInfo *const token) { int c; token->type = TOKEN_UNDEFINED; token->keyword = KEYWORD_NONE; vStringClear (token->string); getNextChar: do { c = fileGetc (); } while (c == '\t' || c == ' ' || c == '\n'); token->lineNumber = getSourceLineNumber (); token->filePosition = getInputFilePosition (); switch (c) { case EOF: longjmp (Exception, (int)ExceptionEOF); break; case '(': token->type = TOKEN_OPEN_PAREN; break; case ')': token->type = TOKEN_CLOSE_PAREN; break; case ';': token->type = TOKEN_SEMICOLON; break; case ',': token->type = TOKEN_COMMA; break; case '.': token->type = TOKEN_PERIOD; break; case ':': token->type = TOKEN_COLON; break; case '{': token->type = TOKEN_OPEN_CURLY; break; case '}': token->type = TOKEN_CLOSE_CURLY; break; case '=': token->type = TOKEN_EQUAL_SIGN; break; case '[': token->type = TOKEN_OPEN_SQUARE; break; case ']': token->type = TOKEN_CLOSE_SQUARE; break; case '\'': case '"': token->type = TOKEN_STRING; parseString (token->string, c); token->lineNumber = getSourceLineNumber (); token->filePosition = getInputFilePosition (); break; case '\\': c = fileGetc (); if (c != '\\' && c != '"' && !isspace (c)) fileUngetc (c); token->type = TOKEN_CHARACTER; token->lineNumber = getSourceLineNumber (); token->filePosition = getInputFilePosition (); break; case '/': { int d = fileGetc (); if ( (d != '*') && /* is this the start of a comment? */ (d != '/') ) /* is a one line comment? */ { fileUngetc (d); switch (LastTokenType) { case TOKEN_CHARACTER: case TOKEN_KEYWORD: case TOKEN_IDENTIFIER: case TOKEN_STRING: case TOKEN_CLOSE_CURLY: case TOKEN_CLOSE_PAREN: case TOKEN_CLOSE_SQUARE: token->type = TOKEN_FORWARD_SLASH; break; default: token->type = TOKEN_REGEXP; parseRegExp (); token->lineNumber = getSourceLineNumber (); token->filePosition = getInputFilePosition (); break; } } else { if (d == '*') { do { skipToCharacter ('*'); c = fileGetc (); if (c == '/') break; else fileUngetc (c); } while (c != EOF && c != '\0'); goto getNextChar; } else if (d == '/') /* is this the start of a comment? */ { skipToCharacter ('\n'); goto getNextChar; } } break; } default: if (! isIdentChar (c)) token->type = TOKEN_UNDEFINED; else { parseIdentifier (token->string, c); token->lineNumber = getSourceLineNumber (); token->filePosition = getInputFilePosition (); token->keyword = analyzeToken (token->string); if (isKeyword (token, KEYWORD_NONE)) token->type = TOKEN_IDENTIFIER; else token->type = TOKEN_KEYWORD; } break; } LastTokenType = token->type; }
static void readTokenFull (tokenInfo *const token, boolean include_newlines, vString *const repr) { int c; int i; token->type = TOKEN_UNDEFINED; token->keyword = KEYWORD_NONE; vStringClear (token->string); getNextChar: i = 0; do { c = fileGetc (); i++; } while (c == '\t' || c == ' ' || ((c == '\r' || c == '\n') && ! include_newlines)); token->lineNumber = getSourceLineNumber (); token->filePosition = getInputFilePosition (); if (repr) { if (i > 1) vStringPut (repr, ' '); vStringPut (repr, c); } switch (c) { case EOF: token->type = TOKEN_EOF; break; case '(': token->type = TOKEN_OPEN_PAREN; break; case ')': token->type = TOKEN_CLOSE_PAREN; break; case ';': token->type = TOKEN_SEMICOLON; break; case ',': token->type = TOKEN_COMMA; break; case '.': token->type = TOKEN_PERIOD; break; case ':': token->type = TOKEN_COLON; break; case '{': token->type = TOKEN_OPEN_CURLY; break; case '}': token->type = TOKEN_CLOSE_CURLY; break; case '=': token->type = TOKEN_EQUAL_SIGN; break; case '[': token->type = TOKEN_OPEN_SQUARE; break; case ']': token->type = TOKEN_CLOSE_SQUARE; break; case '+': case '-': { int d = fileGetc (); if (d == c) /* ++ or -- */ token->type = TOKEN_POSTFIX_OPERATOR; else { fileUngetc (d); token->type = TOKEN_BINARY_OPERATOR; } break; } case '*': case '%': case '?': case '>': case '<': case '^': case '|': case '&': token->type = TOKEN_BINARY_OPERATOR; break; case '\r': case '\n': /* This isn't strictly correct per the standard, but following the * real rules means understanding all statements, and that's not * what the parser currently does. What we do here is a guess, by * avoiding inserting semicolons that would make the statement on * the left invalid. Hopefully this should not have false negatives * (e.g. should not miss insertion of a semicolon) but might have * false positives (e.g. it will wrongfully emit a semicolon for the * newline in "foo\n+bar"). * This should however be mostly harmless as we only deal with * newlines in specific situations where we know a false positive * wouldn't hurt too bad. */ switch (LastTokenType) { /* these cannot be the end of a statement, so hold the newline */ case TOKEN_EQUAL_SIGN: case TOKEN_COLON: case TOKEN_PERIOD: case TOKEN_FORWARD_SLASH: case TOKEN_BINARY_OPERATOR: /* and these already end one, no need to duplicate it */ case TOKEN_SEMICOLON: case TOKEN_COMMA: case TOKEN_CLOSE_CURLY: case TOKEN_OPEN_CURLY: include_newlines = FALSE; /* no need to recheck */ goto getNextChar; break; default: token->type = TOKEN_SEMICOLON; } break; case '\'': case '"': token->type = TOKEN_STRING; parseString (token->string, c); token->lineNumber = getSourceLineNumber (); token->filePosition = getInputFilePosition (); if (repr) { vStringCat (repr, token->string); vStringPut (repr, c); } break; case '\\': c = fileGetc (); if (c != '\\' && c != '"' && !isspace (c)) fileUngetc (c); token->type = TOKEN_CHARACTER; token->lineNumber = getSourceLineNumber (); token->filePosition = getInputFilePosition (); break; case '/': { int d = fileGetc (); if ( (d != '*') && /* is this the start of a comment? */ (d != '/') ) /* is a one line comment? */ { fileUngetc (d); switch (LastTokenType) { case TOKEN_CHARACTER: case TOKEN_IDENTIFIER: case TOKEN_STRING: case TOKEN_CLOSE_CURLY: case TOKEN_CLOSE_PAREN: case TOKEN_CLOSE_SQUARE: token->type = TOKEN_FORWARD_SLASH; break; default: token->type = TOKEN_REGEXP; parseRegExp (); token->lineNumber = getSourceLineNumber (); token->filePosition = getInputFilePosition (); break; } } else { if (repr) /* remove the / we added */ repr->buffer[--repr->length] = 0; if (d == '*') { do { skipToCharacter ('*'); c = fileGetc (); if (c == '/') break; else fileUngetc (c); } while (c != EOF && c != '\0'); goto getNextChar; } else if (d == '/') /* is this the start of a comment? */ { skipToCharacter ('\n'); /* if we care about newlines, put it back so it is seen */ if (include_newlines) fileUngetc ('\n'); goto getNextChar; } } break; } case '#': /* skip shebang in case of e.g. Node.js scripts */ if (token->lineNumber > 1) token->type = TOKEN_UNDEFINED; else if ((c = fileGetc ()) != '!') { fileUngetc (c); token->type = TOKEN_UNDEFINED; } else { skipToCharacter ('\n'); goto getNextChar; } break; default: if (! isIdentChar (c)) token->type = TOKEN_UNDEFINED; else { parseIdentifier (token->string, c); token->lineNumber = getSourceLineNumber (); token->filePosition = getInputFilePosition (); token->keyword = analyzeToken (token->string); if (isKeyword (token, KEYWORD_NONE)) token->type = TOKEN_IDENTIFIER; else token->type = TOKEN_KEYWORD; if (repr && vStringLength (token->string) > 1) vStringCatS (repr, vStringValue (token->string) + 1); } break; } LastTokenType = token->type; }
/* Reads a character from the file */ static void advanceChar (lexerState *lexer) { lexer->cur_c = lexer->next_c; lexer->next_c = fileGetc(); }
static void findBetaTags (void) { vString *line = vStringNew (); boolean incomment = FALSE; boolean inquote = FALSE; boolean dovirtuals = BetaKinds [K_VIRTUAL].enabled; boolean dopatterns = BetaKinds [K_PATTERN].enabled; do { boolean foundfragmenthere = FALSE; /* find fragment definition (line that starts and ends with --) */ int last; int first; int c; vStringClear (line); while ((c = fileGetc ()) != EOF && c != '\n' && c != '\r') vStringPut (line, c); vStringTerminate (line); last = vStringLength (line) - 1; first = 0; /* skip white space at start and end of line */ while (last && isspace ((int) vStringChar (line, last))) last--; while (first < last && isspace ((int) vStringChar (line, first))) first++; /* if line still has a reasonable length and ... */ if (last - first > 4 && (vStringChar (line, first) == '-' && vStringChar (line, first + 1) == '-' && vStringChar (line, last) == '-' && vStringChar (line, last - 1) == '-')) { if (!incomment && !inquote) { foundfragmenthere = TRUE; /* skip past -- and whitespace. Also skip back past 'dopart' or 'attributes' to the :. We have to do this because there is no sensible way to include whitespace in a ctags token so the conventional space after the ':' would mess us up */ last -= 2; first += 2; while (last && vStringChar (line, last) != ':') last--; while (last && (isspace ((int) vStringChar (line, last-1)))) last--; while (first < last && (isspace ((int) vStringChar (line, first)) || vStringChar (line, first) == '-')) first++; /* If there's anything left it is a fragment title */ if (first < last - 1) { vStringChar (line, last) = 0; if (strcasecmp ("LIB", vStringValue (line) + first) && strcasecmp ("PROGRAM", vStringValue (line) + first)) { makeBetaTag (vStringValue (line) + first, K_FRAGMENT); } } } } else { int pos = 0; int len = vStringLength (line); if (inquote) goto stringtext; if (incomment) goto commenttext; programtext: for ( ; pos < len; pos++) { if (vStringChar (line, pos) == '\'') { pos++; inquote = TRUE; goto stringtext; } if (vStringChar (line, pos) == '{') { pos++; incomment = TRUE; goto commenttext; } if (vStringChar (line, pos) == '(' && pos < len - 1 && vStringChar (line, pos+1) == '*') { pos +=2; incomment = TRUE; goto commenttext; } /* * SLOT definition looks like this: * <<SLOT nameofslot: dopart>> * or * <<SLOT nameofslot: descriptor>> */ if (!foundfragmenthere && vStringChar (line, pos) == '<' && pos+1 < len && vStringChar (line, pos+1) == '<' && strstr (vStringValue (line) + pos, ">>")) { /* Found slot name, get start and end */ int eoname; char c2; pos += 2; /* skip past << */ /* skip past space before SLOT */ while (pos < len && isspace ((int) vStringChar (line, pos))) pos++; /* skip past SLOT */ if (pos+4 <= len && !strncasecmp (vStringValue(line) + pos, "SLOT", (size_t)4)) pos += 4; /* skip past space after SLOT */ while (pos < len && isspace ((int) vStringChar (line, pos))) pos++; eoname = pos; /* skip to end of name */ while (eoname < len && (c2 = vStringChar (line, eoname)) != '>' && c2 != ':' && !isspace ((int) c2)) eoname++; if (eoname < len) { vStringChar (line, eoname) = 0; if (strcasecmp ("LIB", vStringValue (line) + pos) && strcasecmp ("PROGRAM", vStringValue (line) + pos) && strcasecmp ("SLOT", vStringValue (line) + pos)) { makeBetaTag (vStringValue (line) + pos, K_SLOT); } } if (eoname+1 < len) { pos = eoname + 1; } else { pos = len; continue; } } /* Only patterns that are virtual, extensions of virtuals or * final bindings are normally included so as not to overload * totally. * That means one of the forms name:: name:< or name::< */ if (!foundfragmenthere && vStringChar (line, pos) == ':' && (dopatterns || (dovirtuals && (vStringChar (line, pos+1) == ':' || vStringChar (line, pos+1) == '<') ) ) ) { /* Found pattern name, get start and end */ int eoname = pos; int soname; while (eoname && isspace ((int) vStringChar (line, eoname-1))) eoname--; foundanothername: /* terminate right after name */ vStringChar (line, eoname) = 0; soname = eoname; while (soname && isbident (vStringChar (line, soname-1))) { soname--; } if (soname != eoname) { makeBetaTag (vStringValue (line) + soname, K_PATTERN); /* scan back past white space */ while (soname && isspace ((int) vStringChar (line, soname-1))) soname--; if (soname && vStringChar (line, soname-1) == ',') { /* we found a new pattern name before comma */ eoname = soname; goto foundanothername; } } } } goto endofline; commenttext: for ( ; pos < len; pos++) { if (vStringChar (line, pos) == '*' && pos < len - 1 && vStringChar (line, pos+1) == ')') { pos += 2; incomment = FALSE; goto programtext; } if (vStringChar (line, pos) == '}') { pos++; incomment = FALSE; goto programtext; } } goto endofline; stringtext: for ( ; pos < len; pos++) { if (vStringChar (line, pos) == '\\') { if (pos < len - 1) pos++; } else if (vStringChar (line, pos) == '\'') { pos++; /* support obsolete '' syntax */ if (pos < len && vStringChar (line, pos) == '\'') { continue; } inquote = FALSE; goto programtext; } } } endofline: inquote = FALSE; /* This shouldn't really make a difference */ } while (!feof (File.fp)); }
static void readToken (tokenInfo * const token) { int c; token->type = TOKEN_NONE; token->keyword = KEYWORD_NONE; vStringClear (token->string); getNextChar: do { c = fileGetc (); token->lineNumber = getSourceLineNumber (); token->filePosition = getInputFilePosition (); } while (c == '\t' || c == ' ' || c == '\n'); switch (c) { case EOF: token->type = TOKEN_EOF; break; case '(': token->type = TOKEN_OPEN_PAREN; break; case ')': token->type = TOKEN_CLOSE_PAREN; break; case ';': token->type = TOKEN_SEMICOLON; break; case '.': token->type = TOKEN_PERIOD; break; case ',': token->type = TOKEN_COMMA; break; case '\'': /* only single char are inside simple quotes */ break; /* or it is for attributes so we don't care */ case '"': token->type = TOKEN_STRING; parseString (token->string, c); token->lineNumber = getSourceLineNumber (); token->filePosition = getInputFilePosition (); break; case '-': c = fileGetc (); if (c == '-') /* start of a comment */ { fileSkipToCharacter ('\n'); goto getNextChar; } else { if (!isspace (c)) fileUngetc (c); token->type = TOKEN_OPERATOR; } break; default: if (!isIdentChar1 (c)) token->type = TOKEN_NONE; else { parseIdentifier (token->string, c); token->lineNumber = getSourceLineNumber (); token->filePosition = getInputFilePosition (); token->keyword = analyzeToken (token->string, Lang_vhdl); if (isKeyword (token, KEYWORD_NONE)) token->type = TOKEN_IDENTIFIER; else token->type = TOKEN_KEYWORD; } break; } }
static void findHaskellTags (int is_literate) { vString *name = vStringNew (); char token[1001], arg[1001]; int c; int in_tex_lit_code = 0; c = get_next_char(); while (c != EOF) { if (c == '\n') { c = get_next_char(); continue; } if (isspace(c)) { skip_rest_of_line(); c = get_next_char(); continue; } if (is_literate && !in_tex_lit_code) { if (c == '>') { c = fileGetc(); if (c == ' ') { c = get_next_char(); if (!isident(c)) { skip_rest_of_line(); c = get_next_char(); continue; } } else { skip_rest_of_line(); c = get_next_char(); continue; } } else if (c == '\\') { int n = get_line(token); if (strncmp(token, "begin{code}", 11) == 0) { in_tex_lit_code = 1; c = get_next_char(); continue; } else { if (n > 0 && token[n-1] != '\n') skip_rest_of_line(); else c = get_next_char(); } continue; } else { skip_rest_of_line(); c = get_next_char(); continue; } } if (is_literate && in_tex_lit_code && c == '\\') { if (strncmp(token, "end{code}", 9) == 0) { in_tex_lit_code = 0; c = get_next_char(); continue; } } token[0] = c; token[1] = '\0'; if (!isident(c)) { skip_rest_of_line(); c = get_next_char(); continue; } if (!get_token(token, 1)) { c = get_next_char(); continue; } do { if ((c = fileGetc()) == EOF) return; } while (c == ' ' || c == '\t'); arg[0] = c; get_token(arg, 1); if (strcmp(token, "data") == 0 || strcmp(token, "newtype") == 0) { add_tag(arg, K_TYPE, name); c = inside_datatype(name); continue; } if (strcmp(token, "type") == 0) add_tag(arg, K_TYPE, name); else if (strcmp(token, "module") == 0) add_tag(arg, K_MODULE, name); else if (strcmp(token, "instance") == 0 || strcmp(token, "foreign") == 0 || strcmp(token, "import") == 0) ; else { if (arg[0] != ':') add_tag(token, K_FUNCTION, name); } skip_rest_of_line(); c = get_next_char(); } vStringDelete(name); }