예제 #1
0
static void
getRestOfHeader(TConn *       const connectionP,
                char *        const lineEnd,
                time_t        const deadline,
                const char ** const headerEndP,
                bool *        const errorP) {
/*----------------------------------------------------------------------------
   Given that the read buffer for connection *connectionP contains (at
   its current read position) the first line of an HTTP header, which
   ends at position 'lineEnd', find the rest of it.

   Some or all of the rest of the header may be in the buffer already;
   we read more from the connection as necessary, but not if it takes past
   'deadline'.  In the latter case, we fail.

   We return the location of the end of the whole header as *headerEndP.
   We do not remove the header from the buffer, but we do modify the
   buffer so as to join the multiple lines of the header into a single
   line, and to NUL-terminate the header.
-----------------------------------------------------------------------------*/
    char * const headerStart = connectionP->buffer.t + connectionP->bufferpos;

    char * headerEnd;
        /* End of the header lines we've seen at so far */
    bool gotWholeHeader;
    bool error;

    headerEnd = lineEnd;  /* initial value - end of 1st line */
        
    for (gotWholeHeader = FALSE, error = FALSE;
         !gotWholeHeader && !error;) {

        char * nextLineEnd;

        /* Note that we are guaranteed, assuming the HTTP stream is
           valid, that there is at least one more line in it.  Worst
           case, it's the empty line that marks the end of the headers.
        */
        getLineInBuffer(connectionP, headerEnd, deadline,
                        &nextLineEnd, &error);
        if (!error) {
            if (isContinuationLine(headerEnd)) {
                /* Join previous line to this one */
                convertLineEnd(headerEnd, headerStart, ' ');
                /* Add this line to the header */
                headerEnd = nextLineEnd;
            } else {
                gotWholeHeader = TRUE;

                /* NUL-terminate the whole header */
                convertLineEnd(headerEnd, headerStart, '\0');
            }
        }
    }
    *headerEndP = headerEnd;
    *errorP     = error;
}
예제 #2
0
/*
    Returns the recommended indent for the bottom line of yyProgram if
    that line is standalone (or should be indented likewise).

    Indenting a standalone line is tricky, mostly because of braceless
    control statements. Grossly, we are looking backwards for a special
    line, a "hook line", that we can use as a starting point to indent,
    and then modify the indentation level according to the braces met
    along the way to that hook.

    Let's consider a few examples. In all cases, we want to indent the
    bottom line.

    Example 1:

        x = 1;
        y = 2;

    The hook line is "x = 1;". We met 0 opening braces and 0 closing
    braces. Therefore, "y = 2;" inherits the indent of "x = 1;".

    Example 2:

        if ( x ) {
            y;

    The hook line is "if ( x ) {". No matter what precedes it, "y;" has
    to be indented one level deeper than the hook line, since we met one
    opening brace along the way.

    Example 3:

        if ( a )
            while ( b ) {
                c;
            }
        d;

    To indent "d;" correctly, we have to go as far as the "if ( a )".
    Compare with

        if ( a ) {
            while ( b ) {
                c;
            }
            d;

    Still, we're striving to go back as little as possible to
    accommodate people with irregular indentation schemes. A hook line
    near at hand is much more reliable than a remote one.
*/
static int indentForStandaloneLine()
{
    for ( int i = 0; i < SmallRoof; i++ ) {
        if ( !*yyLeftBraceFollows ) {
            YY_SAVE();

            if ( matchBracelessControlStatement() ) {
                /*
                    The situation is this, and we want to indent "z;":

                        if ( x &&
                             y )
                            z;

                    yyLine is "if ( x &&".
                */
                return indentOfLine( *yyLine ) + ppIndentSize;
            }
            YY_RESTORE();
        }

        if ( yyLine->endsWith(";") || yyLine->contains('{') ) {
            /*
                The situation is possibly this, and we want to indent
                "z;":

                    while ( x )
                        y;
                    z;

                We return the indent of "while ( x )". In place of "y;",
                any arbitrarily complex compound statement can appear.
            */

            if ( *yyBraceDepth > 0 ) {
                do {
                    if ( !readLine() )
                        break;
                } while ( *yyBraceDepth > 0 );
            }

            LinizerState hookState;

            while ( isContinuationLine() )
                readLine();
            hookState = *yyLinizerState;

            readLine();
            if ( *yyBraceDepth <= 0 ) {
                do {
                    if ( !matchBracelessControlStatement() )
                        break;
                    hookState = *yyLinizerState;
                } while ( readLine() );
            }

            *yyLinizerState = hookState;

            while ( isContinuationLine() )
                readLine();

            /*
              Never trust lines containing only '{' or '}', as some
              people (Richard M. Stallman) format them weirdly.
            */
            if ( yyLine->trimmed().length() > 1 )
                return indentOfLine( *yyLine ) - *yyBraceDepth * ppIndentSize;
        }

        if ( !readLine() )
            return -*yyBraceDepth * ppIndentSize;
    }
    return 0;
}
예제 #3
0
/*
    Returns the recommended indent for the bottom line of yyProgram,
    assuming it's a continuation line.

    We're trying to align the continuation line against some parenthesis
    or other bracked left opened on a previous line, or some interesting
    operator such as '='.
*/
static int indentForContinuationLine()
{
    int braceDepth = 0;
    int delimDepth = 0;

    bool leftBraceFollowed = *yyLeftBraceFollows;

    for ( int i = 0; i < SmallRoof; i++ ) {
        int hook = -1;

        int j = yyLine->length();
        while ( j > 0 && hook < 0 ) {
            j--;
            QChar ch = (*yyLine)[j];

            switch ( ch.unicode() ) {
            case ')':
            case ']':
                delimDepth++;
                break;
            case '}':
                braceDepth++;
                break;
            case '(':
            case '[':
                delimDepth--;
                /*
                    An unclosed delimiter is a good place to align at,
                    at least for some styles (including Trolltech's).
                */
                if ( delimDepth == -1 )
                    hook = j;
                break;
            case '{':
                braceDepth--;
                /*
                    A left brace followed by other stuff on the same
                    line is typically for an enum or an initializer.
                    Such a brace must be treated just like the other
                    delimiters.
                */
                if ( braceDepth == -1 ) {
                    if ( j < (int) yyLine->length() - 1 ) {
                        hook = j;
                    } else {
                        return 0; // shouldn't happen
                    }
                }
                break;
            case '=':
                /*
                    An equal sign is a very natural alignment hook
                    because it's usually the operator with the lowest
                    precedence in statements it appears in. Case in
                    point:

                        int x = 1 +
                                2;

                    However, we have to beware of constructs such as
                    default arguments and explicit enum constant
                    values:

                        void foo( int x = 0,
                                  int y = 0 );

                    And not

                        void foo( int x = 0,
                                        int y = 0 );

                    These constructs are caracterized by a ',' at the
                    end of the unfinished lines or by unbalanced
                    parentheses.
                */
                if ( QString("!=<>").indexOf((*yyLine)[j - 1]) == -1 &&
                     (*yyLine)[j + 1] != '=' ) {
                    if ( braceDepth == 0 && delimDepth == 0 &&
                         j < (int) yyLine->length() - 1 &&
                         !yyLine->endsWith(",") &&
                         (yyLine->contains('(') == yyLine->contains(')')) )
                        hook = j;
                }
            }
        }

        if ( hook >= 0 ) {
            /*
                Yes, we have a delimiter or an operator to align
                against! We don't really align against it, but rather
                against the following token, if any. In this example,
                the following token is "11":

                    int x = ( 11 +
                              2 );

                If there is no such token, we use a continuation indent:

                    static QRegExp foo( QString(
                            "foo foo foo foo foo foo foo foo foo") );
            */
            hook++;
            while ( hook < (int) yyLine->length() ) {
                if ( !(*yyLine)[hook].isSpace() )
                    return columnForIndex( *yyLine, hook );
                hook++;
            }
            return indentOfLine( *yyLine ) + ppContinuationIndentSize;
        }

        if ( braceDepth != 0 )
            break;

        /*
            The line's delimiters are balanced. It looks like a
            continuation line or something.
        */
        if ( delimDepth == 0 ) {
            if ( leftBraceFollowed ) {
                /*
                    We have

                        int main()
                        {

                    or

                        Bar::Bar()
                            : Foo( x )
                        {

                    The "{" should be flush left.
                */
                if ( !isContinuationLine() )
                    return indentOfLine( *yyLine );
            } else if ( isContinuationLine() || yyLine->endsWith(",") ) {
                /*
                    We have

                        x = a +
                            b +
                            c;

                    or

                        int t[] = {
                            1, 2, 3,
                            4, 5, 6

                    The "c;" should fall right under the "b +", and the
                    "4, 5, 6" right under the "1, 2, 3,".
                */
                return indentOfLine( *yyLine );
            } else {
                /*
                    We have

                        stream << 1 +
                                2;

                    We could, but we don't, try to analyze which
                    operator has precedence over which and so on, to
                    obtain the excellent result

                        stream << 1 +
                                  2;

                    We do have a special trick above for the assignment
                    operator above, though.
                */
                return indentOfLine( *yyLine ) + ppContinuationIndentSize;
            }
        }

        if ( !readLine() )
            break;
    }
    return 0;
}
예제 #4
0
static void
readHeader(TConn * const connectionP,
           time_t  const deadline,
           bool *  const endOfHeadersP,
           char ** const headerP,
           bool *  const errorP) {
/*----------------------------------------------------------------------------
   Read an HTTP header, or the end of headers empty line, on connection
   *connectionP.

   An HTTP header is basically a line, except that if a line starts
   with white space, it's a continuation of the previous line.  A line
   is delimited by either LF or CRLF.

   The first line of an HTTP header is never empty; an empty line signals
   the end of the HTTP headers and beginning of the HTTP body.  We call
   that empty line the EOH mark.

   We assume the connection is positioned to a header or EOH mark.
   
   In the course of reading, we read at least one character past the
   line delimiter at the end of the header or EOH mark; we may read
   much more.  But we leave everything after the header or EOH (and
   its line delimiter) in the internal buffer, with the buffer pointer
   pointing to it.

   We use stuff already in the internal buffer (perhaps left by a
   previous call to this subroutine) before reading any more from from
   the channel.

   We return as *headerP the next header as an ASCIIZ string, with no
   line delimiter.  That string is stored in the "unused" portion of
   the connection's internal buffer.  Iff there is no next header, we
   return *endOfHeadersP == true and nothing meaningful as *headerP.
-----------------------------------------------------------------------------*/
    char * const bufferStart = connectionP->buffer.t + connectionP->bufferpos;

    bool error;
    char * lineEnd;

    getLineInBuffer(connectionP, bufferStart, deadline, &lineEnd, &error);

    if (!error) {
        if (isContinuationLine(bufferStart))
            error = TRUE;
        else if (isEmptyLine(bufferStart)) {
            /* Consume the EOH mark from the buffer */
            connectionP->bufferpos = lineEnd - connectionP->buffer.t;
            *endOfHeadersP = TRUE;
        } else {
            /* We have the first line of a header; there may be more. */

            const char * headerEnd;

            *endOfHeadersP = FALSE;

            getRestOfHeader(connectionP, lineEnd, deadline,
                            &headerEnd, &error);

            if (!error) {
                *headerP = bufferStart;

                /* Consume the header from the buffer (but be careful --
                   you can't reuse that part of the buffer because the
                   string we will return is in it!
                */
                connectionP->bufferpos = headerEnd - connectionP->buffer.t;
            }
        }
    }
    *errorP = error;
}
예제 #5
0
void 
pngtxt_addChunk(struct pngx * const pngxP,
                FILE *        const tfP, 
                bool          const ztxt,
                bool          const itxt,
                bool          const verbose) {
/*----------------------------------------------------------------------------
   Add text chunks (tEXt, zTXt, or iTXt) to the PNG image represented by
   *pngxP as directed by file *tfP.

   'itxt' means to make them international language (iTXt) chunks.  Otherwise
   they are either tEXt or zTXt chunks, depending upon 'ztxt'.

   'ztxt' means to make the text compressed.  If the chunks are not
   international (i.e. 'itxt' is false), this means the chunks are zTXt chunks
   instead of 'tEXt' chunks.
-----------------------------------------------------------------------------*/
    bool noChunksYet;
    bool eof;
    png_textp text;  /* An array; one chunk per element */
    unsigned int chunkCt;
        /* Number of chunks we have completed in the 'text' array */
    unsigned int allocatedChunkCt;
        /* Number of entries currently allocated for the PNG text array */

    /* In an international text string file, the first entry tells the
       language of all of the chunks, by having key 'Language'.
    */

    allocatedChunkCt = 256;  /* initial value */

    MALLOCARRAY(text, allocatedChunkCt);
    if (text == NULL) 
        pm_error("unable to allocate memory for text chunk array");

    for (chunkCt = 0, noChunksYet = true, eof = false; !eof; ) {
        const char * textline;
        unsigned int lineLength;

        getFileLine(tfP, &textline, &lineLength);
        if (textline == NULL)
            eof = true;
        else {
            if (lineLength == 0) {
                /* skip this empty line */
            } else {
                handleArrayAllocation(&text, &allocatedChunkCt, chunkCt);

                if (!isContinuationLine(textline)) {
                    png_text * textChunkP;

                    if (noChunksYet) {
                        /* No previous chunk to move past */
                    } else
                        ++chunkCt;
                    noChunksYet = false;
                    
                    textChunkP = &text[chunkCt];
                
                    if (itxt)
                        startTextChunkIntl(textChunkP, 
                                           textline, lineLength, ztxt,
                                           verbose);
                    else
                        startTextChunkEngl(textChunkP, 
                                           textline, lineLength, ztxt,
                                           verbose);
                } else {
                    png_text * const textChunkP = &text[chunkCt];

                    /* Line starts with whitespace, which means it is
                       a continuation of the current text string.
                    */
                    if (noChunksYet)
                        pm_error("Invalid text string file format: "
                                 "first line is a continuation line! "
                                 "(It starts with whitespace)");
                    continueTextString(textChunkP, textline, lineLength);
                }
            }
            pm_strfree(textline);
        }
    }
    if (!noChunksYet)
        ++chunkCt;

    if (verbose)
        reportChunkCt(ztxt, itxt, chunkCt);

    if (chunkCt > 0)
        pngx_setText(pngxP, text, chunkCt);

    free(text);
}