//============================== // ovrLexer::CopyResult void ovrLexer::CopyResult( char const * buffer, char * token, size_t const maxTokenSize ) { // NOTE: if any multi-byte characters are ever treated as quotes, this code must change if ( IsQuote( *buffer ) ) { size_t len = UTF8Util::GetLength( buffer ); const uint32_t lastChar = UTF8Util::GetCharAt( len - 1, buffer ); if ( IsQuote( lastChar ) ) { // The first char and last char are single-byte quotes, we can now just step past the first and not copy the last. char const * start = buffer + 1; len = OVR_strlen( start ); // We do not care about UTF length here since we know the quotes are a single bytes OVR_strncpy( token, maxTokenSize, start, len - 1 ); return; } } OVR_strcpy( token, maxTokenSize, buffer ); }
/**************************************************************************** REMARKS: tells if a character is a letter. replace this when wxWindows gets regex library. (without strange licensing restrictions) ****************************************************************************/ wxString GetEquals( wxString var, wxString value) { if (!wxEchoVariable::Exists(var)) { // TODO: when we implement the set variable, check for a set variable as well #ifdef CHECKED wxMessageBox(wxString("wxHTML #if\\else error: Variable ") + var + wxString(" not found."),"Error",wxICON_ERROR); #endif return wxString("0"); // false } wxString tmp = wxEchoVariable::GetValue(var); if (IsQuote( value.GetChar(0) )) value = value.Mid(1); if (IsQuote(value.GetChar(value.Length()-1))) value = value.Mid(0,value.Length()-1); if (tmp.CmpNoCase(value) == 0) return wxString("1"); return wxString("0"); }
//============================== // ovrLexer::NextToken ovrLexer::ovrResult ovrLexer::NextToken( char * token, size_t const maxTokenSize ) { int const BUFF_SIZE = 8192; char buffer[BUFF_SIZE]; SkipWhitespace( p ); bool inQuotes = false; uint32_t ch = UTF8Util::DecodeNextChar( &p ); ptrdiff_t bufferOfs = 0; while( !IsWhitespace( ch ) || inQuotes ) { if ( ch == '\0' ) { UTF8Util::EncodeChar( buffer, &bufferOfs, '\0' ); CopyResult( buffer, token, maxTokenSize ); return ( bufferOfs <= 1 ) ? LEX_RESULT_EOF : LEX_RESULT_OK; } else if ( IsQuote( ch ) ) { if ( inQuotes ) // if we were in quotes, end the token at the closing quote { UTF8Util::EncodeChar( buffer, &bufferOfs, ch ); UTF8Util::EncodeChar( buffer, &bufferOfs, '\0' ); CopyResult( buffer, token, maxTokenSize ); return LEX_RESULT_OK; } inQuotes = !inQuotes; } int encodeSize = UTF8Util::GetEncodeCharSize( ch ); if ( bufferOfs + encodeSize >= BUFF_SIZE - 1 || bufferOfs + encodeSize + 1 >= (int32_t)maxTokenSize ) { // truncation UTF8Util::EncodeChar( buffer, &bufferOfs, '\0' ); CopyResult( buffer, token, maxTokenSize ); return LEX_RESULT_ERROR; } UTF8Util::EncodeChar( buffer, &bufferOfs, ch ); // decode next character and advance pointer ch = UTF8Util::DecodeNextChar( &p ); } buffer[bufferOfs] = '\0'; CopyResult( buffer, token, maxTokenSize ); return LEX_RESULT_OK; }
void PrintListGeneric(VyParseTree* tree, char oDelim, char cDelim){ printf("%c", oDelim); /* Print each element recursively */ int i; for(i = 0; i < ListTreeSize(tree); i++){ VyParseTree* next = GetListData(tree,i); if(IsQuote(next)){ printf("'"); PrintParseTree(GetListData(next, 1)); } else if(IsSubstitution(next)){ if(IsSplicingSubstitution(next)){ printf("$@"); }else{ printf("$"); } PrintParseTree(GetListData(next, 1)); } else if(next->type == TREE_LIST){ VyParseTree* first = GetListData(next, 0); if(first->type == TREE_IDENT && StrEquals(GetStrData(first), "infix")){ PrintListGeneric(GetListData(next, 1), '{','}'); } else if(first->type == TREE_IDENT && StrEquals(GetStrData(first), "quote-substitutions")){ PrintListGeneric(GetListData(next, 1), '[',']'); }else{ PrintParseTree(next); } } else{ PrintParseTree(next); } } /* If it wasn't an empty list, remove the extra space generated by the item inside */ if(ListTreeSize(tree) > 0){ printf("\b"); } printf("%c ", cDelim); }
static void MacroReplacement (StrBuf* Source, StrBuf* Target) /* Perform macro replacement. */ { ident Ident; Macro* M; /* Remember the current input and switch to Source */ StrBuf* OldSource = InitLine (Source); /* Loop substituting macros */ while (CurC != '\0') { /* If we have an identifier, check if it's a macro */ if (IsSym (Ident)) { /* Check if it's a macro */ if ((M = FindMacro (Ident)) != 0 && !M->Expanding) { /* It's a macro, expand it */ ExpandMacro (Target, M); } else { /* An identifier, keep it */ SB_AppendStr (Target, Ident); } } else if (IsQuote (CurC)) { CopyQuotedString (Target); } else if (IsSpace (CurC)) { if (!IsSpace (SB_LookAtLast (Target))) { SB_AppendChar (Target, CurC); } NextChar (); } else { SB_AppendChar (Target, CurC); NextChar (); } } /* Switch back the input */ InitLine (OldSource); }
static unsigned Pass1 (StrBuf* Source, StrBuf* Target) /* Preprocessor pass 1. Remove whitespace. Handle old and new style comments * and the "defined" operator. */ { unsigned IdentCount; ident Ident; int HaveParen; /* Switch to the new input source */ StrBuf* OldSource = InitLine (Source); /* Loop removing ws and comments */ IdentCount = 0; while (CurC != '\0') { if (SkipWhitespace (0)) { /* Squeeze runs of blanks */ if (!IsSpace (SB_LookAtLast (Target))) { SB_AppendChar (Target, ' '); } } else if (IsSym (Ident)) { if (Preprocessing && strcmp (Ident, "defined") == 0) { /* Handle the "defined" operator */ SkipWhitespace (0); HaveParen = 0; if (CurC == '(') { HaveParen = 1; NextChar (); SkipWhitespace (0); } if (IsSym (Ident)) { SB_AppendChar (Target, IsMacro (Ident)? '1' : '0'); if (HaveParen) { SkipWhitespace (0); if (CurC != ')') { PPError ("`)' expected"); } else { NextChar (); } } } else { PPError ("Identifier expected"); SB_AppendChar (Target, '0'); } } else { ++IdentCount; SB_AppendStr (Target, Ident); } } else if (IsQuote (CurC)) { CopyQuotedString (Target); } else if (CurC == '/' && NextC == '*') { if (!IsSpace (SB_LookAtLast (Target))) { SB_AppendChar (Target, ' '); } OldStyleComment (); } else if (IS_Get (&Standard) >= STD_C99 && CurC == '/' && NextC == '/') { if (!IsSpace (SB_LookAtLast (Target))) { SB_AppendChar (Target, ' '); } NewStyleComment (); } else { SB_AppendChar (Target, CurC); NextChar (); } } /* Switch back to the old source */ InitLine (OldSource); /* Return the number of identifiers found in the line */ return IdentCount; }
static void MacroArgSubst (MacroExp* E) /* Argument substitution according to ISO/IEC 9899:1999 (E), 6.10.3.1ff */ { ident Ident; int ArgIdx; StrBuf* OldSource; StrBuf* Arg; int HaveSpace; /* Remember the current input and switch to the macro replacement. */ int OldIndex = SB_GetIndex (&E->M->Replacement); SB_Reset (&E->M->Replacement); OldSource = InitLine (&E->M->Replacement); /* Argument handling loop */ while (CurC != '\0') { /* If we have an identifier, check if it's a macro */ if (IsSym (Ident)) { /* Check if it's a macro argument */ if ((ArgIdx = FindMacroArg (E->M, Ident)) >= 0) { /* A macro argument. Get the corresponding actual argument. */ Arg = ME_GetActual (E, ArgIdx); /* Copy any following whitespace */ HaveSpace = SkipWhitespace (0); /* If a ## operator follows, we have to insert the actual * argument as is, otherwise it must be macro replaced. */ if (CurC == '#' && NextC == '#') { /* ### Add placemarker if necessary */ SB_Append (&E->Replacement, Arg); } else { /* Replace the formal argument by a macro replaced copy * of the actual. */ SB_Reset (Arg); MacroReplacement (Arg, &E->Replacement); /* If we skipped whitespace before, re-add it now */ if (HaveSpace) { SB_AppendChar (&E->Replacement, ' '); } } } else { /* An identifier, keep it */ SB_AppendStr (&E->Replacement, Ident); } } else if (CurC == '#' && NextC == '#') { /* ## operator. */ NextChar (); NextChar (); SkipWhitespace (0); /* Since we need to concatenate the token sequences, remove * any whitespace that was added to target, since it must come * from the input. */ while (IsSpace (SB_LookAtLast (&E->Replacement))) { SB_Drop (&E->Replacement, 1); } /* If the next token is an identifier which is a macro argument, * replace it, otherwise do nothing. */ if (IsSym (Ident)) { /* Check if it's a macro argument */ if ((ArgIdx = FindMacroArg (E->M, Ident)) >= 0) { /* Get the corresponding actual argument and add it. */ SB_Append (&E->Replacement, ME_GetActual (E, ArgIdx)); } else { /* Just an ordinary identifier - add as is */ SB_AppendStr (&E->Replacement, Ident); } } } else if (CurC == '#' && E->M->ArgCount >= 0) { /* A # operator within a macro expansion of a function like * macro. Read the following identifier and check if it's a * macro parameter. */ NextChar (); SkipWhitespace (0); if (!IsSym (Ident) || (ArgIdx = FindMacroArg (E->M, Ident)) < 0) { PPError ("`#' is not followed by a macro parameter"); } else { /* Make a valid string from Replacement */ Arg = ME_GetActual (E, ArgIdx); SB_Reset (Arg); Stringize (Arg, &E->Replacement); } } else if (IsQuote (CurC)) { CopyQuotedString (&E->Replacement); } else { SB_AppendChar (&E->Replacement, CurC); NextChar (); } } #if 0 /* Remove whitespace from the end of the line */ while (IsSpace (SB_LookAtLast (&E->Replacement))) { SB_Drop (&E->Replacement, 1); } #endif /* Switch back the input */ InitLine (OldSource); SB_SetIndex (&E->M->Replacement, OldIndex); }
static void ReadMacroArgs (MacroExp* E) /* Identify the arguments to a macro call */ { unsigned Parens; /* Number of open parenthesis */ StrBuf Arg = STATIC_STRBUF_INITIALIZER; /* Read the actual macro arguments */ Parens = 0; while (1) { if (CurC == '(') { /* Nested parenthesis */ SB_AppendChar (&Arg, CurC); NextChar (); ++Parens; } else if (IsQuote (CurC)) { /* Quoted string - just copy */ CopyQuotedString (&Arg); } else if (CurC == ',' || CurC == ')') { if (Parens) { /* Comma or right paren inside nested parenthesis */ if (CurC == ')') { --Parens; } SB_AppendChar (&Arg, CurC); NextChar (); } else if (CurC == ',' && ME_ArgIsVariadic (E)) { /* It's a comma, but we're inside a variadic macro argument, so * just copy it and proceed. */ SB_AppendChar (&Arg, CurC); NextChar (); } else { /* End of actual argument. Remove whitespace from the end. */ while (IsSpace (SB_LookAtLast (&Arg))) { SB_Drop (&Arg, 1); } /* If this is not the single empty argument for a macro with * an empty argument list, remember it. */ if (CurC != ')' || SB_NotEmpty (&Arg) || E->M->ArgCount > 0) { ME_AppendActual (E, &Arg); } /* Check for end of macro param list */ if (CurC == ')') { NextChar (); break; } /* Start the next param */ NextChar (); SB_Clear (&Arg); } } else if (SkipWhitespace (1)) { /* Squeeze runs of blanks within an arg */ if (SB_NotEmpty (&Arg)) { SB_AppendChar (&Arg, ' '); } } else if (CurC == '/' && NextC == '*') { if (SB_NotEmpty (&Arg)) { SB_AppendChar (&Arg, ' '); } OldStyleComment (); } else if (IS_Get (&Standard) >= STD_C99 && CurC == '/' && NextC == '/') { if (SB_NotEmpty (&Arg)) { SB_AppendChar (&Arg, ' '); } NewStyleComment (); } else if (CurC == '\0') { /* End of input inside macro argument list */ PPError ("Unterminated argument list invoking macro `%s'", E->M->Name); ClearLine (); break; } else { /* Just copy the character */ SB_AppendChar (&Arg, CurC); NextChar (); } } /* Deallocate string buf resources */ SB_Done (&Arg); }