void QScriptCompletionTaskPrivate::completeScriptExpression() { int pos = cursorPosition; if ((pos > 0) && contents.at(pos-1).isNumber()) { // completion of numbers is pointless emitFinished(); return; } while ((pos > 0) && isIdentChar(contents.at(pos-1))) --pos; int pos2 = cursorPosition - 1; while ((pos2+1 < contents.size()) && isIdentChar(contents.at(pos2+1))) ++pos2; QString ident = contents.mid(pos, pos2 - pos + 1); position = pos; QStringList path; path.append(ident); while ((pos > 0) && (contents.at(pos-1) == QLatin1Char('.'))) { --pos; pos2 = pos; while ((pos > 0) && isIdentChar(contents.at(pos-1))) --pos; path.prepend(contents.mid(pos, pos2 - pos)); } length = path.last().length(); type = QScriptCompletionTask::ScriptIdentifierCompletion; QScriptDebuggerJob *job = new QScriptCompleteExpressionJob(frameIndex, path, this, commandScheduler); jobScheduler->scheduleJob(job); }
/*! \reimp */ bool QScriptDebuggerCodeView::event(QEvent *e) { Q_D(QScriptDebuggerCodeView); if (e->type() == QEvent::ToolTip) { if (d->editor->executionLineNumber() == -1) return false; QHelpEvent *he = static_cast<QHelpEvent*>(e); QPoint pt = he->pos(); pt.rx() -= d->editor->extraAreaWidth(); pt.ry() -= 8; QTextCursor cursor = d->editor->cursorForPosition(pt); QTextBlock block = cursor.block(); QString contents = block.text(); if (contents.isEmpty()) return false; int linePosition = cursor.position() - block.position(); linePosition -= 3; if (linePosition < 0) linePosition = 0; // ### generalize -- same as in completiontask int pos = linePosition; if ((pos > 0) && contents.at(pos-1).isNumber()) { // tooltips for numbers is pointless return false; } while ((pos > 0) && isIdentChar(contents.at(pos-1))) --pos; if ((pos > 0) && ((contents.at(pos-1) == QLatin1Char('\'')) || (contents.at(pos-1) == QLatin1Char('\"')))) { // ignore string literals return false; } int pos2 = linePosition; while ((pos2 < contents.size()-1) && isIdentChar(contents.at(pos2+1))) ++pos2; QString ident = contents.mid(pos, pos2 - pos + 1); QStringList path; path.append(ident); while ((pos > 0) && (contents.at(pos-1) == QLatin1Char('.'))) { --pos; pos2 = pos; while ((pos > 0) && isIdentChar(contents.at(pos-1))) --pos; path.prepend(contents.mid(pos, pos2 - pos)); } if (!path.isEmpty()) { int lineNumber = cursor.blockNumber() + d->editor->baseLineNumber(); emit toolTipRequest(he->globalPos(), lineNumber, path); } } return false; }
/* 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 */ }
QvBool QvName::isIdentStartChar(char c) { if (isdigit(c)) return FALSE; return isIdentChar(c); }
GvBool GvName::isNodeNameStartChar(char c,GvBool vrml2) { if (vrml2) return(isIdentStartChar(c,vrml2)); // VRML 1.0 // ////// if (isdigit(c)) return FALSE; return isIdentChar(c,vrml2); }
static void parseIdentifier (vString *const string, const int firstChar) { int c = firstChar; do { vStringPut (string, (char) c); c = getcFromInputFile (); } while (isIdentChar (c)); ungetcToInputFile (c); }
static void parseIdentifier (vString *const string, const int firstChar) { int c = firstChar; do { vStringPut (string, c); c = getcFromInputFile (); } while (isIdentChar (c)); vStringTerminate (string); ungetcToInputFile (c); /* always unget, LF might add a semicolon */ }
/* Read a VHDL identifier beginning with "firstChar" and place it into "name". */ static void parseIdentifier (vString * const string, const int firstChar) { int c = firstChar; Assert (isIdentChar1 (c)); do { vStringPut (string, c); c = getcFromInputFile (); } while (isIdentChar (c)); if (!isspace (c)) ungetcToInputFile (c); /* unget non-identifier character */ }
GvBool GvName::isNodeNameChar(char c,GvBool vrml2) { if (vrml2) return(isIdentChar(c,vrml2)); // VRML 1.0 if (isalnum(c)) return TRUE; // (0x00 .. 0x1F or 0x7F) iscntl(c) removed 7.10.96 if ((strchr(badCharacters, c) != NULL) || isspace(c)) return FALSE; return TRUE; }
void processLine(char *line) { char *p; int quoteType; static char fnm[300]; char *fname; int nn; p = line; while(isspace(*p)) p++; if (!*p) goto addToMaster; // see if the first thing on the line is an include directive if (*p=='.') p++; if (strnicmp(p, "include", 7)==0 && !isIdentChar(p[7])) { p += 7; // Capture the file name while(isspace(*p)) p++; if (*p=='"') { quoteType = '"'; p++; } else if (*p=='<') { quoteType = '>'; p++; } else quoteType = ' '; nn = 0; do { fnm[nn] = *p; p++; nn++; if (quoteType==' ' && isspace(*p)) break; else if (*p == quoteType) break; else if (*p=='\n') break; } while(nn < sizeof(fnm)/sizeof(char)); fnm[nn] = '\0'; fname = strdup(fnm); processFile(fname,1); free(fname); return; } // Not an include directive, then just copy the line to the master buffer. addToMaster: strcpy(&masterFile[mfndx], line); mfndx += strlen(line); }
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; }
GvBool GvName::isIdentStartChar(char c,GvBool vrml2) { if (isdigit(c)) return FALSE; return isIdentChar(c,vrml2); }
static void findShTags (void) { vString *name = vStringNew (); const unsigned char *line; vString *hereDocDelimiter = NULL; boolean hereDocIndented = FALSE; boolean (* check_char)(int); while ((line = fileReadLine ()) != NULL) { const unsigned char* cp = line; shKind found_kind = K_NOTHING; if (hereDocDelimiter) { if (hereDocIndented) { while (*cp == '\t') cp++; } if (strcmp ((const char *) cp, vStringValue (hereDocDelimiter)) == 0) { vStringDelete (hereDocDelimiter); hereDocDelimiter = NULL; } continue; } while (*cp != '\0') { /* jump over whitespace */ while (isspace ((int)*cp)) cp++; /* jump over strings */ if (*cp == '"') cp = skipDoubleString (cp); else if (*cp == '\'') cp = skipSingleString (cp); /* jump over comments */ else if (*cp == '#') break; /* jump over here-documents */ else if (cp[0] == '<' && cp[1] == '<') { const unsigned char *start, *end; boolean trimEscapeSequences = FALSE; boolean quoted = FALSE; cp += 2; /* an optional "-" strips leading tabulations from the heredoc lines */ if (*cp != '-') hereDocIndented = FALSE; else { hereDocIndented = TRUE; cp++; } while (isspace (*cp)) cp++; start = end = cp; /* the delimiter can be surrounded by quotes */ if (*cp == '"') { start++; end = cp = skipDoubleString (cp); /* we need not to worry about variable substitution, they * don't happen in heredoc delimiter definition */ trimEscapeSequences = TRUE; quoted = TRUE; } else if (*cp == '\'') { start++; end = cp = skipSingleString (cp); quoted = TRUE; } else { while (isIdentChar ((int) *cp)) cp++; end = cp; } if (end > start || quoted) { /* The input may be broken as a shell script but we need to avoid memory leaking. */ if (hereDocDelimiter) vStringClear(hereDocDelimiter); else hereDocDelimiter = vStringNew (); for (; end > start; start++) { if (trimEscapeSequences && *start == '\\') start++; vStringPut (hereDocDelimiter, *start); } } } if (strncmp ((const char*) cp, "function", (size_t) 8) == 0 && isspace ((int) cp [8])) { found_kind = K_FUNCTION; cp += 8; } else if (strncmp ((const char*) cp, "alias", (size_t) 5) == 0 && isspace ((int) cp [5])) { found_kind = K_ALIAS; cp += 5; } else if (cp [0] == '.' && isspace((int) cp [1])) { found_kind = K_SOURCE; ++cp; } else if (strncmp ((const char*) cp, "source", (size_t) 6) == 0 && isspace((int) cp [6])) { found_kind = K_SOURCE; cp += 6; } if (found_kind != K_NOTHING) while (isspace ((int) *cp)) ++cp; // Get the name of the function, alias or file to be read by source check_char = isIdentChar; if (found_kind == K_SOURCE) check_char = isFileChar; if (! check_char ((int) *cp)) { found_kind = K_NOTHING; if (*cp != '\0') ++cp; continue; } while (check_char ((int) *cp)) { vStringPut (name, (int) *cp); ++cp; } vStringTerminate (name); while (isspace ((int) *cp)) ++cp; if ((found_kind != K_SOURCE) && *cp == '(') { ++cp; while (isspace ((int) *cp)) ++cp; if (*cp == ')') { found_kind = K_FUNCTION; ++cp; } } if (found_kind != K_NOTHING) { makeSimpleTag (name, ShKinds, found_kind); found_kind = K_NOTHING; } vStringClear (name); } } vStringDelete (name); if (hereDocDelimiter) vStringDelete (hereDocDelimiter); }
/** * evallabel replace "...%2i..." occurences in label with value of i */ static const char * evalLabel (const char* src, Tree visited, Tree localValEnv) { //std::cerr << "Eval Label : " << src; int state = 0; // current state std::string dst; // label once evaluated std::string ident; // current identifier std::string format; // current format while (state != -1) { char c = *src++; if (state == 0) { if (c == 0) { state = -1; } else if (c == '%') { ident = ""; format = ""; state = 1; } else { dst+=c; state = 0; } } else if (state == 1) { if (c == 0) { // fin et pas d'indentifiant, abandon dst += '%'; dst += format; state = -1; } else if (isDigitChar(c)) { format += c; state = 1; } else if (isIdentChar(c)) { ident += c; state = 2; } else { // caractere de ponctuation et pas d'indentifiant, abandon dst += '%'; dst += format; src--; state = 0; } } else if (state == 2) { if (isIdentChar(c)) { ident += c; state = 2; } else { writeIdentValue(dst, format, ident, visited, localValEnv); src--; state = 0; } } else { stringstream error; error << "internal error in evallabel : undefined state " << state << std::endl; throw faustexception(error.str()); } } const char* val = strdup(dst.c_str()); //std::cerr << " ===> " << val << std::endl; return val; }
static void readToken (tokenInfo *const token) { int c; token->type = TOKEN_UNDEFINED; token->keyword = KEYWORD_NONE; vStringClear (token->string); getNextChar: if (! InPhp) { c = findPhpStart (); if (c != EOF) InPhp = TRUE; } else c = getcFromInputFile (); c = skipWhitespaces (c); token->lineNumber = getInputLineNumber (); token->filePosition = getInputFilePosition (); 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_OPEN_SQUARE; break; case ']': token->type = TOKEN_CLOSE_SQUARE; break; case '&': token->type = TOKEN_AMPERSAND; break; case '\\': token->type = TOKEN_BACKSLASH; break; case '=': { int d = getcFromInputFile (); if (d == '=' || d == '>') token->type = TOKEN_OPERATOR; else { ungetcToInputFile (d); token->type = TOKEN_EQUAL_SIGN; } break; } case '\'': case '"': token->type = TOKEN_STRING; parseString (token->string, c); token->lineNumber = getInputLineNumber (); token->filePosition = getInputFilePosition (); break; case '<': { int d = getcFromInputFile (); if (d == '/') { /* </script[:white:]*> */ if (tolower ((d = getcFromInputFile ())) == 's' && tolower ((d = getcFromInputFile ())) == 'c' && tolower ((d = getcFromInputFile ())) == 'r' && tolower ((d = getcFromInputFile ())) == 'i' && tolower ((d = getcFromInputFile ())) == 'p' && tolower ((d = getcFromInputFile ())) == 't' && (d = skipWhitespaces (getcFromInputFile ())) == '>') { InPhp = FALSE; goto getNextChar; } else { ungetcToInputFile (d); token->type = TOKEN_UNDEFINED; } } else if (d == '<' && (d = getcFromInputFile ()) == '<') { token->type = TOKEN_STRING; parseHeredoc (token->string); } else { ungetcToInputFile (d); token->type = TOKEN_UNDEFINED; } break; } case '#': /* comment */ skipSingleComment (); goto getNextChar; break; case '+': case '-': case '*': case '%': { int d = getcFromInputFile (); if (d != '=' && ! (c == '-' && d == '>')) ungetcToInputFile (d); token->type = TOKEN_OPERATOR; break; } case '/': /* division or comment start */ { int d = getcFromInputFile (); if (d == '/') /* single-line comment */ { skipSingleComment (); goto getNextChar; } else if (d == '*') { do { c = skipToCharacter ('*'); if (c != EOF) { c = getcFromInputFile (); if (c == '/') break; else ungetcToInputFile (c); } } while (c != EOF && c != '\0'); goto getNextChar; } else { if (d != '=') ungetcToInputFile (d); token->type = TOKEN_OPERATOR; } break; } case '$': /* variable start */ { int d = getcFromInputFile (); if (! isIdentChar (d)) { ungetcToInputFile (d); token->type = TOKEN_UNDEFINED; } else { parseIdentifier (token->string, d); token->type = TOKEN_VARIABLE; } break; } case '?': /* maybe the end of the PHP chunk */ { int d = getcFromInputFile (); if (d == '>') { InPhp = FALSE; goto getNextChar; } else { ungetcToInputFile (d); token->type = TOKEN_UNDEFINED; } break; } default: if (! isIdentChar (c)) token->type = TOKEN_UNDEFINED; else { parseIdentifier (token->string, c); token->keyword = analyzeToken (token->string, getInputLanguage ()); if (token->keyword == KEYWORD_NONE) token->type = TOKEN_IDENTIFIER; else token->type = TOKEN_KEYWORD; } break; } if (token->type == TOKEN_SEMICOLON || token->type == TOKEN_OPEN_CURLY || token->type == TOKEN_CLOSE_CURLY) { /* reset current statement details on statement end, and when entering * a deeper scope. * it is a bit ugly to do this in readToken(), but it makes everything * a lot simpler. */ CurrentStatement.access = ACCESS_UNDEFINED; CurrentStatement.impl = IMPL_UNDEFINED; } }
/* reads an HereDoc or a NowDoc (the part after the <<<). * <<<[ \t]*(ID|'ID'|"ID") * ... * ID;? * * note that: * 1) starting ID must be immediately followed by a newline; * 2) closing ID is the same as opening one; * 3) closing ID must be immediately followed by a newline or a semicolon * then a newline. * * Example of a *single* valid heredoc: * <<< FOO * something * something else * FOO this is not an end * FOO; this isn't either * FOO; # neither this is * FOO; * # previous line was the end, but the semicolon wasn't required */ static void parseHeredoc (vString *const string) { int c; unsigned int len; char delimiter[64]; /* arbitrary limit, but more is crazy anyway */ int quote = 0; do { c = getcFromInputFile (); } while (c == ' ' || c == '\t'); if (c == '\'' || c == '"') { quote = c; c = getcFromInputFile (); } for (len = 0; len < ARRAY_SIZE (delimiter) - 1; len++) { if (! isIdentChar (c)) break; delimiter[len] = (char) c; c = getcFromInputFile (); } delimiter[len] = 0; if (len == 0) /* no delimiter, give up */ goto error; if (quote) { if (c != quote) /* no closing quote for quoted identifier, give up */ goto error; c = getcFromInputFile (); } if (c != '\r' && c != '\n') /* missing newline, give up */ goto error; do { c = getcFromInputFile (); if (c != '\r' && c != '\n') vStringPut (string, (char) c); else { /* new line, check for a delimiter right after */ int nl = c; int extra = EOF; c = getcFromInputFile (); for (len = 0; c != 0 && (c - delimiter[len]) == 0; len++) c = getcFromInputFile (); if (delimiter[len] != 0) ungetcToInputFile (c); else { /* line start matched the delimiter, now check whether there * is anything after it */ if (c == '\r' || c == '\n') { ungetcToInputFile (c); break; } else if (c == ';') { int d = getcFromInputFile (); if (d == '\r' || d == '\n') { /* put back the semicolon since it's not part of the * string. we can't put back the newline, but it's a * whitespace character nobody cares about it anyway */ ungetcToInputFile (';'); break; } else { /* put semicolon in the string and continue */ extra = ';'; ungetcToInputFile (d); } } } /* if we are here it wasn't a delimiter, so put everything in the * string */ vStringPut (string, (char) nl); vStringNCatS (string, delimiter, len); if (extra != EOF) vStringPut (string, (char) extra); } } while (c != EOF); vStringTerminate (string); return; error: ungetcToInputFile (c); }
/* * Copies the characters forming an identifier from *cp into * name, leaving *cp pointing to the character after the identifier. */ static rubyKind parseIdentifier ( const unsigned char** cp, vString* name, rubyKind kind) { /* Method names are slightly different to class and variable names. * A method name may optionally end with a question mark, exclamation * point or equals sign. These are all part of the name. * A method name may also contain a period if it's a singleton method. */ boolean had_sep = FALSE; const char* also_ok; if (kind == K_METHOD) { also_ok = ".?!="; } else if (kind == K_SINGLETON) { also_ok = "?!="; } else { also_ok = ""; } skipWhitespace (cp); /* Check for an anonymous (singleton) class such as "class << HTTP". */ if (kind == K_CLASS && **cp == '<' && *(*cp + 1) == '<') { return K_UNDEFINED; } /* Check for operators such as "def []=(key, val)". */ if (kind == K_METHOD || kind == K_SINGLETON) { if (parseRubyOperator (name, cp)) { return kind; } } /* Copy the identifier into 'name'. */ while (**cp != 0 && (**cp == ':' || isIdentChar (**cp) || charIsIn (**cp, also_ok))) { char last_char = **cp; if (last_char == ':') had_sep = TRUE; else { if (had_sep) { vStringPut (name, SCOPE_SEPARATOR); had_sep = FALSE; } vStringPut (name, last_char); } ++*cp; if (kind == K_METHOD) { /* Recognize singleton methods. */ if (last_char == '.') { vStringTerminate (name); vStringClear (name); return parseIdentifier (cp, name, K_SINGLETON); } } if (kind == K_METHOD || kind == K_SINGLETON) { /* Recognize characters which mark the end of a method name. */ if (charIsIn (last_char, "?!=")) { break; } } } return kind; }
static void readToken (tokenInfo *const token) { int c; token->type = TOKEN_UNDEFINED; vStringClear (token->string); getNextChar: c = getcFromInputFile (); c = skipWhitespaces (c); token->lineNumber = getInputLineNumber (); token->filePosition = getInputFilePosition (); 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_OPEN_SQUARE; break; case ']': token->type = TOKEN_CLOSE_SQUARE; break; case '=': token->type = TOKEN_EQUAL_SIGN; break; case '\'': case '"': token->type = TOKEN_STRING; parseString (token->string, c); token->lineNumber = getInputLineNumber (); token->filePosition = getInputFilePosition (); break; case '<': { int d = getcFromInputFile (); if (d == '#') { /* <# ... #> multiline comment */ do { c = skipToCharacterInInputFile ('#'); if (c != EOF) { c = getcFromInputFile (); if (c == '>') break; else ungetcToInputFile (c); } } while (c != EOF); goto getNextChar; } else { ungetcToInputFile (d); token->type = TOKEN_UNDEFINED; } break; } case '#': /* comment */ skipSingleComment (); goto getNextChar; break; case '+': case '-': case '*': case '/': case '%': { int d = getcFromInputFile (); if (d != '=') ungetcToInputFile (d); token->type = TOKEN_OPERATOR; break; } case '$': /* variable start */ { int d = getcFromInputFile (); if (! isIdentChar (d)) { ungetcToInputFile (d); token->type = TOKEN_UNDEFINED; } else { parseIdentifier (token->string, d); token->type = TOKEN_VARIABLE; } break; } default: if (! isIdentChar (c)) token->type = TOKEN_UNDEFINED; else { parseIdentifier (token->string, c); if (isTokenFunction (token->string)) token->type = TOKEN_KEYWORD; else token->type = TOKEN_IDENTIFIER; } break; } }
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; }
/* * Extract a list of features from a table. */ static List * analyzeTable(const char * table) { static char fileName[MAXSTRING]; char ** resolved; List * features = NULL; FileInfo info; int k; resolved = resolveTable(table, NULL); if (resolved == NULL) { logMessage(LOG_ERROR, "Cannot resolve table '%s'", table); return NULL; } sprintf(fileName, "%s", *resolved); k = 0; for (k = 0; resolved[k]; k++) free(resolved[k]); free(resolved); if (k > 1) { logMessage(LOG_ERROR, "Table '%s' resolves to more than one file", table); return NULL; } info.fileName = fileName; info.encoding = noEncoding; info.status = 0; info.lineNumber = 0; if ((info.in = fopen(info.fileName, "rb"))) { while (getALine(&info)) { if (info.linelen == 0); else if (info.line[0] == '#') { if (info.linelen >= 2 && info.line[1] == '+') { widechar * key = NULL; widechar * val = NULL; size_t keySize = 0; size_t valSize = 0; info.linepos = 2; if (info.linepos < info.linelen && isIdentChar(info.line[info.linepos])) { key = &info.line[info.linepos]; keySize = 1; info.linepos++; while (info.linepos < info.linelen && isIdentChar(info.line[info.linepos])) { keySize++; info.linepos++; } if (info.linepos < info.linelen && info.line[info.linepos] == ':') { info.linepos++; while (info.linepos < info.linelen && (info.line[info.linepos] == ' ' || info.line[info.linepos] == '\t')) info.linepos++; if (info.linepos < info.linelen && isIdentChar(info.line[info.linepos])) { val = &info.line[info.linepos]; valSize = 1; info.linepos++; while (info.linepos < info.linelen && isIdentChar(info.line[info.linepos])) { valSize++; info.linepos++; } } else goto compile_error; } if (info.linepos == info.linelen) { char * k = widestrToStr(key, keySize); char * v = val ? widestrToStr(val, valSize) : NULL; Feature f = feature_new(k, v); logMessage(LOG_DEBUG, "Table has feature '%s:%s'", f.key, f.val); features = list_conj(features, memcpy(malloc(sizeof(f)), &f, sizeof(f)), NULL, NULL, (void (*)(void *))feature_free); free(k); free(v); } else goto compile_error; } else goto compile_error; } } else break; } fclose(info.in); } else logMessage (LOG_ERROR, "Cannot open table '%s'", info.fileName); return list_sort(features, (int (*)(void *, void *))cmpKeys); compile_error: if (info.linepos < info.linelen) logMessage(LOG_ERROR, "Unexpected character '%c' on line %d, column %d", info.line[info.linepos], info.lineNumber, info.linepos); else logMessage(LOG_ERROR, "Unexpected newline on line %d", info.lineNumber); list_free(features); return NULL; }
/* * Parse a table query into a list of features. Features defined first get a * higher importance. */ static List * parseQuery(const char * query) { List * features = NULL; const char * key = NULL; const char * val = NULL; size_t keySize = 0; size_t valSize = 0; const char * c; int pos = 0; while (1) { c = &query[pos++]; if (*c == ' ' || *c == '\t' || *c == '\n' | *c == '\0') { if (key) { char * k = strndup(key, keySize); char * v = val ? strndup(val, valSize) : NULL; FeatureWithImportance f = { feature_new(k, v), 0 }; logMessage(LOG_DEBUG, "Query has feature '%s:%s'", f.feature.key, f.feature.val); features = list_conj(features, memcpy(malloc(sizeof(f)), &f, sizeof(f)), NULL, NULL, (void (*)(void *))feature_free); free(k); free(v); key = val = NULL; keySize = valSize = 0; } if (*c == '\0') break; } else if (*c == ':') { if (!key || val) goto compile_error; else { c = &query[pos++]; if (isIdentChar(*c)) { val = c; valSize = 1; } else goto compile_error; } } else if (isIdentChar(*c)) { if (val) valSize++; else if (key) keySize++; else { key = c; keySize = 1; } } else goto compile_error; } int k = 1; List * l; for (l = features; l; l = l->tail) { FeatureWithImportance * f = l->head; f->importance = k++; } return list_sort(features, (int (*)(void *, void *))cmpKeys); compile_error: logMessage(LOG_ERROR, "Unexpected character '%c' at position %d", c, pos); list_free(features); return NULL; }
static void readTokenFull (tokenInfo *const token, boolean includeStringRepr) { int c; token->type = TOKEN_UNDEFINED; vStringClear (token->string); do c = getcFromInputFile (); while (c == '\t' || c == ' ' || c == '\r' || c == '\n'); token->lineNumber = getInputLineNumber (); token->filePosition = getInputFilePosition (); switch (c) { case EOF: token->type = TOKEN_EOF; break; case '[': token->type = TOKEN_OPEN_SQUARE; break; case ']': token->type = TOKEN_CLOSE_SQUARE; break; case '{': token->type = TOKEN_OPEN_CURLY; break; case '}': token->type = TOKEN_CLOSE_CURLY; break; case ':': token->type = TOKEN_COLON; break; case ',': token->type = TOKEN_COMMA; break; case '"': { boolean escaped = FALSE; token->type = TOKEN_STRING; while (TRUE) { c = getcFromInputFile (); /* we don't handle unicode escapes but they are safe */ if (escaped) escaped = FALSE; else if (c == '\\') escaped = TRUE; else if (c >= 0x00 && c <= 0x1F) break; /* break on invalid, unescaped, control characters */ else if (c == '"' || c == EOF) break; if (includeStringRepr) vStringPut (token->string, c); } vStringTerminate (token->string); break; } default: if (! isIdentChar (c)) token->type = TOKEN_UNDEFINED; else { do { vStringPut (token->string, c); c = getcFromInputFile (); } while (c != EOF && isIdentChar (c)); vStringTerminate (token->string); ungetcToInputFile (c); switch (lookupKeyword (vStringValue (token->string), Lang_json)) { case KEYWORD_true: token->type = TOKEN_TRUE; break; case KEYWORD_false: token->type = TOKEN_FALSE; break; case KEYWORD_null: token->type = TOKEN_NULL; break; default: token->type = TOKEN_NUMBER; break; } } break; } }
static void readTokenFull (tokenInfo *const token, boolean include_newlines, vString *const repr) { int c; int i; boolean newline_encountered = FALSE; /* if we've got a token held back, emit it */ if (NextToken) { copyToken (token, NextToken, FALSE); deleteToken (NextToken); NextToken = NULL; return; } token->type = TOKEN_UNDEFINED; token->keyword = KEYWORD_NONE; vStringClear (token->string); getNextChar: i = 0; do { c = fileGetc (); if (include_newlines && (c == '\r' || c == '\n')) newline_encountered = TRUE; i++; } while (c == '\t' || c == ' ' || c == '\r' || c == '\n'); 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 '\'': 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 '`': token->type = TOKEN_TEMPLATE_STRING; parseTemplateString (token->string); 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_TEMPLATE_STRING: case TOKEN_CLOSE_CURLY: case TOKEN_CLOSE_PAREN: case TOKEN_CLOSE_SQUARE: token->type = TOKEN_BINARY_OPERATOR; 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 { fileSkipToCharacter ('*'); 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? */ { fileSkipToCharacter ('\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 { fileSkipToCharacter ('\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, Lang_js); 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; } if (include_newlines && newline_encountered) { /* 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 or right obviously 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 sometimes, i.e. 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. */ /* these already end a statement, so no need to duplicate it */ #define IS_STMT_SEPARATOR(t) ((t) == TOKEN_SEMICOLON || \ (t) == TOKEN_EOF || \ (t) == TOKEN_COMMA || \ (t) == TOKEN_CLOSE_CURLY || \ (t) == TOKEN_OPEN_CURLY) /* these cannot be the start or end of a statement */ #define IS_BINARY_OPERATOR(t) ((t) == TOKEN_EQUAL_SIGN || \ (t) == TOKEN_COLON || \ (t) == TOKEN_PERIOD || \ (t) == TOKEN_BINARY_OPERATOR) if (! IS_STMT_SEPARATOR(LastTokenType) && ! IS_STMT_SEPARATOR(token->type) && ! IS_BINARY_OPERATOR(LastTokenType) && ! IS_BINARY_OPERATOR(token->type) && /* these cannot be followed by a semicolon */ ! (LastTokenType == TOKEN_OPEN_PAREN || LastTokenType == TOKEN_OPEN_SQUARE)) { /* hold the token... */ Assert (NextToken == NULL); NextToken = newToken (); copyToken (NextToken, token, FALSE); /* ...and emit a semicolon instead */ token->type = TOKEN_SEMICOLON; token->keyword = KEYWORD_NONE; vStringClear (token->string); if (repr) vStringPut (token->string, '\n'); } #undef IS_STMT_SEPARATOR #undef IS_BINARY_OPERATOR } LastTokenType = token->type; }
static boolean notIdentChar (int c) { return ! isIdentChar (c); }
static void readToken (tokenInfo *const token) { int c; token->type = TOKEN_UNDEFINED; 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: 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 '?': token->type = TOKEN_QUESTION_MARK; break; case '*': token->type = TOKEN_STAR; break; case '\'': case '"': token->type = TOKEN_STRING; parseString (token->string, c); token->lineNumber = getSourceLineNumber (); token->filePosition = getInputFilePosition (); break; case '\\': /* * All Tex tags start with a backslash. * Check if the next character is an alpha character * else it is not a potential tex tag. */ c = fileGetc (); if (! isalpha (c)) fileUngetc (c); else { parseIdentifier (token->string, c); token->lineNumber = getSourceLineNumber (); token->filePosition = getInputFilePosition (); token->keyword = analyzeToken (token->string, Lang_js); if (isKeyword (token, KEYWORD_NONE)) token->type = TOKEN_IDENTIFIER; else token->type = TOKEN_KEYWORD; } break; case '%': fileSkipToCharacter ('\n'); /* % are single line comments */ goto getNextChar; break; default: if (! isIdentChar (c)) token->type = TOKEN_UNDEFINED; else { parseIdentifier (token->string, c); token->lineNumber = getSourceLineNumber (); token->filePosition = getInputFilePosition (); token->type = TOKEN_IDENTIFIER; } break; } }
static void findRubyTags (void) { const unsigned char *line; boolean inMultiLineComment = FALSE; nesting = nestingLevelsNew (0); /* FIXME: this whole scheme is wrong, because Ruby isn't line-based. * You could perfectly well write: * * def * method * puts("hello") * end * * if you wished, and this function would fail to recognize anything. */ while ((line = readLineFromInputFile ()) != NULL) { const unsigned char *cp = line; /* if we expect a separator after a while, for, or until statement * separators are "do", ";" or newline */ boolean expect_separator = FALSE; if (canMatch (&cp, "=begin", isWhitespace)) { inMultiLineComment = TRUE; continue; } if (canMatch (&cp, "=end", isWhitespace)) { inMultiLineComment = FALSE; continue; } if (inMultiLineComment) continue; skipWhitespace (&cp); /* Avoid mistakenly starting a scope for modifiers such as * * return if <exp> * * FIXME: this is fooled by code such as * * result = if <exp> * <a> * else * <b> * end * * FIXME: we're also fooled if someone does something heinous such as * * puts("hello") \ * unless <exp> */ if (canMatchKeyword (&cp, "for") || canMatchKeyword (&cp, "until") || canMatchKeyword (&cp, "while")) { expect_separator = TRUE; enterUnnamedScope (); } else if (canMatchKeyword (&cp, "case") || canMatchKeyword (&cp, "if") || canMatchKeyword (&cp, "unless")) { enterUnnamedScope (); } /* * "module M", "class C" and "def m" should only be at the beginning * of a line. */ if (canMatchKeyword (&cp, "module")) { readAndEmitTag (&cp, K_MODULE); } else if (canMatchKeyword (&cp, "class")) { readAndEmitTag (&cp, K_CLASS); } else if (canMatchKeyword (&cp, "def")) { rubyKind kind = K_METHOD; NestingLevel *nl = nestingLevelsGetCurrent (nesting); tagEntryInfo *e = getEntryOfNestingLevel (nl); /* if the def is inside an unnamed scope at the class level, assume * it's from a singleton from a construct like this: * * class C * class << self * def singleton * ... * end * end * end */ if (e && (e->kind - RubyKinds) == K_CLASS && strlen (e->name) == 0) kind = K_SINGLETON; readAndEmitTag (&cp, kind); } while (*cp != '\0') { /* FIXME: we don't cope with here documents, * or regular expression literals, or ... you get the idea. * Hopefully, the restriction above that insists on seeing * definitions at the starts of lines should keep us out of * mischief. */ if (inMultiLineComment || isspace (*cp)) { ++cp; } else if (*cp == '#') { /* FIXME: this is wrong, but there *probably* won't be a * definition after an interpolated string (where # doesn't * mean 'comment'). */ break; } else if (canMatchKeyword (&cp, "begin")) { enterUnnamedScope (); } else if (canMatchKeyword (&cp, "do")) { if (! expect_separator) enterUnnamedScope (); else expect_separator = FALSE; } else if (canMatchKeyword (&cp, "end") && nesting->n > 0) { /* Leave the most recent scope. */ nestingLevelsPop (nesting); } else if (*cp == '"') { /* Skip string literals. * FIXME: should cope with escapes and interpolation. */ do { ++cp; } while (*cp != 0 && *cp != '"'); if (*cp == '"') cp++; /* skip the last found '"' */ } else if (*cp == ';') { ++cp; expect_separator = FALSE; } else if (*cp != '\0') { do ++cp; while (isIdentChar (*cp)); } } } nestingLevelsFree (nesting); }
void processSegments() { char *pinptr; int segment; if (verbose) printf("Processing segments.\r\n"); inptr = &masterFile[0]; pinptr = inptr; codendx = 0; datandx = 0; rodatandx = 0; tlsndx = 0; bssndx = 0; memset(codebuf,0,sizeof(codebuf)); memset(databuf,0,sizeof(databuf)); memset(rodatabuf,0,sizeof(rodatabuf)); memset(tlsbuf,0,sizeof(tlsbuf)); memset(bssbuf,0,sizeof(bssbuf)); while (*inptr) { SkipSpaces(); if (*inptr=='.') inptr++; if ((strnicmp(inptr,"code",4)==0) && !isIdentChar(inptr[4])) { segment = codeseg; } else if ((strnicmp(inptr,"data",4)==0) && !isIdentChar(inptr[4])) { segment = dataseg; } else if ((strnicmp(inptr,"rodata",6)==0) && !isIdentChar(inptr[6])) { segment = rodataseg; } else if ((strnicmp(inptr,"tls",3)==0) && !isIdentChar(inptr[3])) { segment = tlsseg; } else if ((strnicmp(inptr,"bss",3)==0) && !isIdentChar(inptr[3])) { segment = bssseg; } ScanToEOL(); inptr++; switch(segment) { case codeseg: strncpy(&codebuf[codendx], pinptr, inptr-pinptr); codendx += inptr-pinptr; break; case dataseg: strncpy(&databuf[datandx], pinptr, inptr-pinptr); datandx += inptr-pinptr; break; case rodataseg: strncpy(&rodatabuf[rodatandx], pinptr, inptr-pinptr); rodatandx += inptr-pinptr; break; case tlsseg: strncpy(&tlsbuf[tlsndx], pinptr, inptr-pinptr); tlsndx += inptr-pinptr; break; case bssseg: strncpy(&bssbuf[bssndx], pinptr, inptr-pinptr); bssndx += inptr-pinptr; break; } pinptr = inptr; } memset(masterFile,0,sizeof(masterFile)); strcpy(masterFile, codebuf); strcat(masterFile, rodatabuf); strcat(masterFile, databuf); strcat(masterFile, bssbuf); strcat(masterFile, tlsbuf); if (debug) { FILE *fp; fp = fopen("a64-segments.asm", "w"); if (fp) { fwrite(masterFile, 1, strlen(masterFile), fp); fclose(fp); } } }