Esempio n. 1
0
  //----------------------------------------------------------------------------------------------------
  // Support for jint Atomic::add(jint inc, volatile jint* dest).
  //
  // Arguments:
  //
  //     inc  - GR_I0 (e.g., +1 or -1)
  //     dest - GR_I1
  //
  // Results:
  //
  //     GR_RET - the new value stored in dest
  //
  //
  address generate_atomic_add() {
    StubCodeMark mark(this, "StubRoutines", "atomic_add");

    const Register inc  = GR_I0;
    const Register dest = GR_I1;

    address start = __ emit_fd();

    __ mf();

    // increment or decrement
    __ cmp4(PR6, PR7, 1, inc, Assembler::equal);

    __ fetchadd4(PR6, GR_RET, dest,  1, Assembler::acquire);
    __ fetchadd4(PR7, GR_RET, dest, -1, Assembler::acquire);

    // GR_RET contains result of the fetch, not the add
    __ sxt4(GR_RET, GR_RET);
    __ adds(PR6, GR_RET,  1, GR_RET);
    __ adds(PR7, GR_RET, -1, GR_RET);

    __ ret();

    return start;
  }
Esempio n. 2
0
int main()
{
	int a = A, b = B;
	unsigned ua = uA;
	unsigned ub = uB;
	unsigned uc = uC;

	printf("cmp1(%d, %d) = %d\n", a, b, cmp1(a, b));
	printf("cmp2(%d, %d) = %d\n", a, b, cmp2(a, b));
	printf("cmp3(%d) = %d\n", a, cmp3(a));
	printf("cmp4(%d) = %d\n", a, cmp4(a));
	printf("cmp5(%d) = %d\n", a, cmp5(a));
	printf("cmp6(%d) = %d\n", a, cmp6(a));
	printf("cmp7(%d) = %d\n", a, cmp7(a));
	printf("cmp8(%d) = %d\n", a, cmp8(a));
	printf("cmp9(%d, %d) = %d\n", a, b, cmp9(a, b));
	printf("cmp10(%d, %d) = %d\n", a, b, cmp10(a, b));
	printf("cmp11(%d) = %d\n", a, cmp11(a));
	printf("cmp12(%d) = %d\n", a, cmp12(a));
	printf("cmp13(%d) = %d\n", a, cmp13(a));
	printf("cmp14(%d) = %d\n", a, cmp14(a));
	printf("cmp15(%d) = %d\n", a, cmp15(a));
	printf("cmp16(%d) = %d\n", a, cmp16(a));
	printf("cmp17(%d, %d) = %d\n", a, b, cmp17(a, b));
	printf("cmp18(%d, %d) = %d\n", a, b, cmp18(a, b));

	printf("cmp19(%u, %u) = %d\n", ua, ub, cmp19(ua, ub));
	printf("cmp20(%u, %u) = %d\n", ua, ub, cmp20(ua, ub));
	printf("cmp21(%u, %u) = %d\n", ua, ub, cmp21(ua, ub));
	printf("cmp22(%u, %u) = %d\n", ua, ub, cmp22(ua, ub));
	printf("cmp23(%u, %u) = %d\n", ua, ub, cmp23(ua, ub));

	printf("cmp19(%u, %u) = %d\n", ua, uc, cmp19(ua, uc));
	printf("cmp20(%u, %u) = %d\n", ua, uc, cmp20(ua, uc));
	printf("cmp21(%u, %u) = %d\n", ua, uc, cmp21(ua, uc));
	printf("cmp22(%u, %u) = %d\n", ua, uc, cmp22(ua, uc));
	printf("cmp23(%u, %u) = %d\n", ua, uc, cmp23(ua, uc));

	return 0;
}
Esempio n. 3
0
  //------------------------------------------------------------------------------------------------------------------------
  // Call stubs are used to call Java from C
  //
  // GR_I0 - call wrapper address     : address
  // GR_I1 - result                   : intptr_t*
  // GR_I2 - result type              : BasicType
  // GR_I3 - method                   : methodOop
  // GR_I4 - interpreter entry point  : address
  // GR_I5 - parameter block          : intptr_t*
  // GR_I6 - parameter count in words : int
  // GR_I7 - thread                   : Thread*
  //
  address generate_call_stub(address& return_address) {
    StubCodeMark mark(this, "StubRoutines", "call_stub");

    const Register result     = GR_I1;
    const Register type       = GR_I2;
    const Register method     = GR_I3;
    const Register entry_ptr  = GR_I4;
    const Register parms      = GR_I5;
    const Register parm_count = GR_I6;
    const Register thread     = GR_I7;

    const Register parm_size = GR31_SCRATCH;
    const Register entry     = GR30_SCRATCH;
    const Register arg       = GR29_SCRATCH;

    const Register out_tos   = GR49; // Equivalent of GR_Otos
    const Register out_parms = GR50; // Equivalent of GR_Olocals (unused)

    const BranchRegister    entry_br = BR6_SCRATCH;
    const PredicateRegister no_args  = PR6_SCRATCH;

    address start = __ emit_fd();

    // Must allocate 8 output registers in case we go thru an i2c
    // and the callee needs 8 input registers
    __ alloc(GR_Lsave_PFS, 8, 9, 8, 0);                     // save AR_PFS
    __ sxt4(parm_count, parm_count);                        // # of parms
    __ mov(GR_Lsave_SP, SP);                                // save caller's SP
    __ mov(GR_entry_frame_GR5, GR5_poll_page_addr);
    __ mov(GR_entry_frame_GR6, GR6_caller_BSP);
    __ mov(GR_entry_frame_GR7, GR7_reg_stack_limit);

    // We can not tolerate an eager RSE cpu. Itanium-1 & 2 do not support
    // this feature but we turn it off anyway
    const Register RSC   = GR2_SCRATCH;
    __ mov(RSC, AR_RSC);
    __ and3(RSC, -4, RSC);      // Turn off two low bits
    __ mov(AR_RSC, RSC);        //  enforced lazy mode

    __ shladd(parm_size, parm_count, Interpreter::logStackElementSize(), GR0); // size of stack space for the parms
    __ mov(GR_Lsave_RP, RP);                                // save return address

    __ add(parm_size, parm_size, 15);                       // round up to multiple of 16 bytes.  we use
                                                            // caller's 16-byte scratch area for params,
                                                            // so no need to add 16 to the current frame size.
    __ mov(GR_Lsave_LC, AR_LC);                             // save AR_LC
    __ add(out_parms, SP, Interpreter::stackElementSize());      // caller's SP+8 is 1st parm addr == target method locals addr

    __ and3(parm_size, parm_size, -16);
    __ cmp4(PR0, no_args, 0, parm_count, Assembler::less);  // any parms?

    __ mov(GR_entry_frame_GR4, GR4_thread);                 // save GR4_thread: it's a preserved register
    __ sub(SP, SP, parm_size);                              // allocate the space for args + scratch
    __ mov(entry_br, entry_ptr);

    __ mov(GR27_method, method);                            // load method
    __ mov(GR4_thread, thread);                             // load thread
    if (TaggedStackInterpreter) __ shl(parm_count, parm_count, 1);  // 2x tags
    __ sub(parm_count, parm_count, 1);                      // cloop counts down to zero

    // Initialize the register and memory stack limits for stack checking in compiled code
    __ add(GR7_reg_stack_limit, thread_(register_stack_limit));
    __ mov(GR6_caller_BSP, AR_BSP);                         // load register SP
    __ movl(GR5_poll_page_addr, (intptr_t) os::get_polling_page() );
    __ ld8(GR7_reg_stack_limit, GR7_reg_stack_limit);       // load register stack limit

    Label exit;

    __ mov(AR_LC, parm_count);
    __ mov(out_tos, out_parms);                             // out_tos = &out_parms[0]
    __ br(no_args, exit, Assembler::dpnt);

    // Reverse argument list and set up sender tos

    Label copy_word;
    __ bind(copy_word);

    __ ld8(arg, parms, BytesPerWord);                       // load *parms++
    __ st8(out_tos, arg, -BytesPerWord);                    // store *out_tos--
    __ cloop(copy_word, Assembler::sptk, Assembler::few);

    // Bias stack for tags.
    if (TaggedStackInterpreter) __ st8(out_tos, GR0, -BytesPerWord);
    __ bind(exit);

    __ mov(GR_entry_frame_TOS, out_tos);                    // so entry_frame_argument_at can find TOS

    // call interpreter frame manager

    // Remember the senderSP so we interpreter can pop c2i arguments off of the stack
    // when called via a c2i.

    __ mov(GR28_sender_SP, SP);

    __ call(entry_br);

    return_address = __ pc();

    // Store result depending on type.  Everything that is not
    // T_OBJECT, T_LONG, T_FLOAT, or T_DOUBLE is treated as T_INT.

    const PredicateRegister is_obj = PR6_SCRATCH;
    const PredicateRegister is_flt = PR7_SCRATCH;
    const PredicateRegister is_dbl = PR8_SCRATCH;
    const PredicateRegister is_lng = PR9_SCRATCH;

    __ cmp4(is_obj, PR0,    T_OBJECT, type, Assembler::equal);
    __ cmp4(is_flt, PR0,    T_FLOAT,  type, Assembler::equal);
    __ st4( result, GR_RET);

    __ st8( is_obj, result, GR_RET);
    __ stfs(is_flt, result, FR_RET);
    __ cmp4(is_dbl, PR0,    T_DOUBLE, type, Assembler::equal);

    __ stfd(is_dbl, result, FR_RET);
    __ cmp4(is_lng, PR0,    T_LONG,   type, Assembler::equal);
    __ mov(RP, GR_Lsave_RP);

    __ st8( is_lng, result, GR_RET);
    __ mov(GR4_thread, GR_entry_frame_GR4);

    __ mov(GR6_caller_BSP, GR_entry_frame_GR6);
    __ mov(GR7_reg_stack_limit, GR_entry_frame_GR7);
    __ mov(GR5_poll_page_addr, GR_entry_frame_GR5);
    __ mov(AR_PFS, GR_Lsave_PFS);

    __ mov(AR_LC, GR_Lsave_LC);
    __ mov(SP, GR_Lsave_SP);
    __ ret();

    return start;
  }
Esempio n. 4
0
void ControllerServer::process_command( gpointer connection, ConnectionInfo & info, gchar ** parts , bool * read_again )
{
    guint count = g_strv_length( parts );

    if ( count < 1 )
    {
        return;
    }

    const gchar * cmd = parts[0];

    if ( strlen( cmd ) < 2 )
    {
        return;
    }

    if ( cmp2( cmd, "ID" ) )
    {
        // Device id line
        // ID <version> <name> <cap>*

        * read_again = false;

        // Not enough parts

        if ( count < 3 )
        {
            return;
        }

        // Already have a version

        if ( info.version )
        {
            return;
        }


        info.version = atoi( parts[1] );

        if ( !info.version )
        {
            return;
        }

        if ( info.version < 2 )
        {
            g_warning( "CONTROLLER DOES NOT SUPPORT PROTOCOL VERSION >= 2" );
            info.version = 0;
            return;
        }

        if ( info.version < 3 )
        {
            g_warning( "CONTROLLER DOES NOT SUPPORT PROTOCOL VERSION >= 3" );
            info.version = 0;
            return;
        }

        if ( info.version < 4 )
        {
            g_warning( "CONTROLLER DOES NOT SUPPORT PROTOCOL VERSION >= 4" );
            info.version = 0;
            return;
        }

        const char * name = g_strstrip( parts[2] );

        // Capability entries

        TPControllerSpec spec;

        memset( &spec, 0, sizeof( spec ) );

        for ( guint i = 3; i < count; ++i )
        {
            const gchar * cap = g_strstrip( parts[i] );

            size_t len = strlen( cap );

            if ( len == 2 )
            {
                if ( cmp2( cap, "KY" ) )
                {
                    spec.capabilities |= TP_CONTROLLER_HAS_KEYS;
                }
                else if ( cmp2( cap, "AX" ) )
                {
                    spec.capabilities |= TP_CONTROLLER_HAS_ACCELEROMETER;
                }
                else if ( cmp2( cap, "FM" ) )
                {
                    spec.capabilities |= TP_CONTROLLER_HAS_FULL_MOTION;
                }
                else if ( cmp2( cap, "PT" ) )
                {
                    spec.capabilities |= TP_CONTROLLER_HAS_POINTER;
                }
                else if ( cmp2( cap, "CK" ) )
                {
                    // Deprecated
                    // spec.capabilities |= TP_CONTROLLER_HAS_CLICKS;
                }
                else if ( cmp2( cap, "TC" ) )
                {
                    spec.capabilities |= TP_CONTROLLER_HAS_TOUCHES;
                }
                else if ( cmp2( cap, "MC" ) )
                {
                    spec.capabilities |= TP_CONTROLLER_HAS_MULTIPLE_CHOICE;
                }
                else if ( cmp2( cap, "SD" ) )
                {
                    spec.capabilities |= TP_CONTROLLER_HAS_SOUND;
                }
                else if ( cmp2( cap, "UI" ) )
                {
                    spec.capabilities |= TP_CONTROLLER_HAS_UI;
                }
                else if ( cmp2( cap, "TE" ) )
                {
                    spec.capabilities |= TP_CONTROLLER_HAS_TEXT_ENTRY;
                }
                else if ( cmp2( cap, "PS" ) )
				{
					spec.capabilities |= TP_CONTROLLER_HAS_IMAGES;
				}
                else if ( cmp2( cap, "AC" ) )
				{
					spec.capabilities |= TP_CONTROLLER_HAS_AUDIO_CLIPS;
				}
                else if ( cmp2( cap , "UX" ) )
                {
                    spec.capabilities |= TP_CONTROLLER_HAS_ADVANCED_UI;
                }
                else if ( cmp2( cap , "VR" ) )
                {
                	spec.capabilities |= TP_CONTROLLER_HAS_VIRTUAL_REMOTE;
                }
                else if ( cmp2( cap , "SV" ) )
                {
                	spec.capabilities |= TP_CONTROLLER_HAS_STREAMING_VIDEO;
                }
                else
                {
                    g_warning( "UNKNOWN CONTROLLER CAPABILITY '%s'", cap );
                }
            }
            else if ( len > 3 )
            {
                if ( cmp2( cap, "IS" ) )
                {
                    sscanf( cap, "IS=%ux%u", &spec.input_width, &spec.input_height );
                }
                else if ( cmp2( cap, "US" ) )
                {
                    sscanf( cap, "US=%ux%u", &spec.ui_width, &spec.ui_height );
                }
                else if ( cmp2( cap , "ID" ) )
                {
                	spec.id = cap + 3;
                }
                else
                {
                    g_warning( "UNKNOWN CONTROLLER CAPABILITY '%s'", cap );
                }
            }
        }

        * read_again = true;

        spec.execute_command = execute_command;

        info.controller = tp_context_add_controller( context, name, &spec, this );

        server->write_printf( connection , "WM\t%s\t%u\t%lu\n" , CONTROLLER_PROTOCOL_VERSION , context->get_http_server()->get_port() , info.aui_id );
    }
    else if ( cmp2( cmd, "KP" ) )
    {
        // Key press
        // KP <hex key code> <hex unicode>

        if ( count < 2 || !info.controller )
        {
            return;
        }

        unsigned int key_code = 0;
        unsigned long int unicode = 0;

        sscanf( parts[1], "%x", &key_code );

        if ( count > 2 )
        {
            sscanf( parts[2], "%lx", &unicode );
        }

        tp_controller_key_down( info.controller, key_code, unicode , TP_CONTROLLER_MODIFIER_NONE );
        tp_controller_key_up( info.controller, key_code, unicode , TP_CONTROLLER_MODIFIER_NONE );
    }
    else if ( cmp2( cmd, "KD" ) )
    {
        // Key down
        // KD <hex key code> <hex unicode>

        if ( count < 2 || !info.controller )
        {
            return;
        }

        unsigned int key_code = 0;
        unsigned long int unicode = 0;

        sscanf( parts[1], "%x", &key_code );

        if ( count > 2 )
        {
            sscanf( parts[2], "%lx", &unicode );
        }

        tp_controller_key_down( info.controller, key_code, unicode , TP_CONTROLLER_MODIFIER_NONE );
    }
    else if ( cmp2( cmd, "KU" ) )
    {
        // Key up
        // KU <hex key code> <hex unicode>

        if ( count < 2 || !info.controller )
        {
            return;
        }

        unsigned int key_code = 0;
        unsigned long int unicode = 0;

        sscanf( parts[1], "%x", &key_code );

        if ( count > 2 )
        {
            sscanf( parts[2], "%lx", &unicode );
        }

        tp_controller_key_up( info.controller, key_code, unicode , TP_CONTROLLER_MODIFIER_NONE );
    }
    else if ( cmp2( cmd, "CK" ) )
    {
        // Click
        // CK <x> <y>

        // deprecated

        return;
    }
    else if ( cmp2( cmd, "AX" ) )
    {
        // Acelerometer
        // AX <x> <y> <z>

        if ( count < 4 || !info.controller )
        {
            return;
        }

        tp_controller_accelerometer( info.controller, atof( parts[1] ), atof( parts[2] ), atof( parts[3] ) , TP_CONTROLLER_MODIFIER_NONE );
    }
    else if ( cmp2( cmd, "GY" ) )
    {
        // Acelerometer
        // AX <x> <y> <z>

        if ( count < 4 || !info.controller )
        {
            return;
        }

        tp_controller_gyroscope( info.controller, atof( parts[1] ), atof( parts[2] ), atof( parts[3] ) , TP_CONTROLLER_MODIFIER_NONE );
    }
    else if ( cmp2( cmd, "MM" ) )
    {
        // Acelerometer
        // AX <x> <y> <z>

        if ( count < 4 || !info.controller )
        {
            return;
        }

        tp_controller_magnetometer( info.controller, atof( parts[1] ), atof( parts[2] ), atof( parts[3] ) , TP_CONTROLLER_MODIFIER_NONE );
    }
    else if ( cmp2( cmd, "AT" ) )
    {
        // Acelerometer
        // AX <x> <y> <z>

        if ( count < 4 || !info.controller )
        {
            return;
        }

        tp_controller_attitude( info.controller, atof( parts[1] ), atof( parts[2] ), atof( parts[3] ) , TP_CONTROLLER_MODIFIER_NONE );
    }
    else if ( cmp2( cmd, "UI" ) )
    {
        // UI
        // UI <type> <txt>

        if ( count < 2 || !info.controller || strlen(parts[1]) != 2)
        {
            return;
        }

        // Enter text or multiple-choice
        if(cmp2( parts[1], "ET") || cmp2( parts[1], "MC"))
        {
            if(count < 3)
            {
                return;
            }
            tp_controller_ui_event( info.controller, parts[2] );
        }
        // Advanced UI event
        else if (cmp2( parts[1] , "UX" ) )
        {
        	if ( count < 3 )
        	{
        		return;
        	}
        	tp_controller_advanced_ui_event( info.controller , parts[ 2 ] );
        }
        // Cancel image
        else if(cmp2( parts[1], "CI"))
        {
            tp_controller_cancel_image( info.controller );
        }
        // Cancel audio
        else if(cmp2( parts[1], "CA"))
        {
            tp_controller_cancel_audio_clip( info.controller );
        }
    }
    else if ( cmp2( cmd, "PD" ) )
    {
        // Pointer button down
        // PD <button> <x> <y>

        if ( count < 4 || !info.controller )
        {
            return;
        }

        tp_controller_pointer_button_down( info.controller, atoi( parts[1] ), atoi( parts[2] ) , atoi( parts[ 3 ] ) , TP_CONTROLLER_MODIFIER_NONE );
    }
    else if ( cmp2( cmd, "PM" ) )
    {
        // Pointer move
        // PM <x> <y>

        if ( count < 3 || !info.controller )
        {
            return;
        }

        tp_controller_pointer_move( info.controller, atoi( parts[1] ), atoi( parts[2] ) , TP_CONTROLLER_MODIFIER_NONE );
    }
    else if ( cmp2( cmd, "PU" ) )
    {
        // Pointer button up
        // PU <button> <x> <y>

        if ( count < 4 || !info.controller )
        {
            return;
        }

        tp_controller_pointer_button_up( info.controller, atoi( parts[1] ), atoi( parts[2] ) , atoi( parts[ 3 ] ) , TP_CONTROLLER_MODIFIER_NONE );
    }
    else if ( cmp2( cmd, "TD" ) )
    {
        // Touch down
        // TD <finger> <x> <y>

        if ( count < 4 || !info.controller )
        {
            return;
        }

        tp_controller_touch_down( info.controller, atoi( parts[1] ), atoi( parts[2] ) , atoi( parts[ 3 ] ) , TP_CONTROLLER_MODIFIER_NONE );
    }
    else if ( cmp2( cmd, "TM" ) )
    {
        // Touch move
        // TM <finger> <x> <y>

        if ( count < 4 || !info.controller )
        {
            return;
        }

        tp_controller_touch_move( info.controller, atoi( parts[1] ), atoi( parts[2] ) , atoi( parts[ 3 ] ) , TP_CONTROLLER_MODIFIER_NONE );
    }
    else if ( cmp2( cmd, "TU" ) )
    {
        // Touch up
        // TU <finger> <x> <y>

        if ( count < 4 || !info.controller )
        {
            return;
        }

        tp_controller_touch_up( info.controller, atoi( parts[1] ), atoi( parts[2] ) , atoi( parts[ 3 ] ) , TP_CONTROLLER_MODIFIER_NONE );
    }
    else if ( cmp2( cmd , "UX" ) )
    {
        // Stop reading from this connection. We will only read
        // synchronously after we write. If there is a problem with the UX message,
        // we stop reading anyway - they only get one shot at it.

        * read_again = false;

        if ( count < 2 )
        {
            return;
        }

        gulong id = 0;

        if ( sscanf( parts[1], "%lu", & id ) != 1 )
        {
            return;
        }

        // The ID is bad

        if ( id == 0 )
        {
            return;
        }

        ConnectionInfo * parent_info = 0;

        for ( ConnectionMap::iterator it = connections.begin(); it != connections.end(); ++it )
        {
            if ( it->second.aui_id == id )
            {
                parent_info = & it->second;
                break;
            }
        }

        // Could not find a connection for this ID

        if ( ! parent_info )
        {
            return;
        }

        // The controller connection for this ID has not identified itself yet

        if ( ! parent_info->version )
        {
            return;
        }

        // OK, everything is cool

        // Set this connection's version, so it does not get booted.

        info.version = parent_info->version;

        // Tell the parent that this connection belongs to it

        parent_info->aui_connection = connection;

        // Now, generate the event that it is ready

        tp_controller_advanced_ui_ready( parent_info->controller );
    }
    else if ( cmp4( cmd, "SVCC" ) )
    {
        // Streaming video call connected
        // SVCC <address>

        if ( count < 2 || !info.controller )
        {
            return;
        }

        tp_controller_streaming_video_connected( info.controller, parts[1] );
    }
    else if ( cmp4( cmd, "SVCF" ) )
    {
        // Streaming video call failed
        // SVCF <address> <reason>

        if ( count < 3 || !info.controller )
        {
            return;
        }

        tp_controller_streaming_video_failed( info.controller, parts[1], parts[2] );
    }
    else if ( cmp4( cmd, "SVCD" ) )
    {
        // Streaming video call was dropped
        // SVCD <address> <reason>

        if ( count < 3 || !info.controller )
        {
            return;
        }

        tp_controller_streaming_video_dropped( info.controller, parts[1], parts[2] );
    }
    else if ( cmp4( cmd, "SVCE" ) )
    {
        // Streaming video call ended
        // SVCE <address> <who>

        if ( count < 3 || !info.controller )
        {
            return;
        }

        tp_controller_streaming_video_ended( info.controller, parts[1], parts[2] );
    }
    else if ( cmp4( cmd, "SVCS" ) )
    {
        // Streaming video call status
        // SVCS <status> <address>

        if ( count < 3 || !info.controller )
        {
            return;
        }

        tp_controller_streaming_video_status( info.controller, parts[1], parts[2] );
    }
    else
    {
        g_warning( "UNKNOWN CONTROLLER COMMAND '%s'", cmd );
    }
}
Esempio n. 5
0
int main() {
  char line[8192];
  char* dat;
  char* timestamp;
#ifdef oldandslow
  setvbuf(stdout,printfbuf,_IOFBF,sizeof printfbuf);
  while (fgets(line,sizeof(line),stdin)) {
    int tslen;
    /* chomp */
    {
      int i;
      for (i=0; i<sizeof(line) && line[i]; ++i)
	if (line[i]=='\n') break;
      line[i]=0;
    }
#else
  buffer_init(buffer_1,write,1,printfbuf,sizeof printfbuf);
  while (myfgets(line,sizeof(line))+1>1) {
    int tslen;
#endif
    /* find out what kind of time stamp there is */
    tslen=0;
    if (line[0]=='@') {
      /* multilog timestamp */
      char* x=strchr(line,' ');
      if (x) {
	tslen=x-line;
	if (tslen!=25) tslen=0;
      }
    } else if (isdigit(line[0])) {
      char* x=strchr(line,' ');
      if (x && x==line+10) {
	x=strchr(x+1,' ');
	if (x && x==line+29) tslen=29;
      }
    }
    if (tslen) {
      dat=line+tslen+1;
      line[tslen]=0;
      timestamp=line;
    } else {
      dat=line;
      timestamp="";
    }
    /* element two is the unique key */
    {
      char* fields[21];
      char* x=dat;
      int i;

      /* early-out skip the field splitting if we are not interested in
       * the line anyway */
      if (*x != 'a' && *x != 'c' && *x != 'G' && *x != 'P' && *x != 'H')
	continue;

      /* split into fields */
      for (i=0; i<20; ++i) {
	char* y=strchr(x,' ');
	if (!y) break;
	*y=0;
	fields[i]=x;
	x=y+1;
      }
      fields[i]=x; ++i;
      if (!strcmp(fields[0],"accept")) {
	struct node** N;
	struct node* x;
	if (i<2) continue;
	N=lookup(fields[1]);
	if (!(x=*N)) {
	  *N=malloc(sizeof(**N));
	  (*N)->next=0;
	  x=*N;
	} else {
	  free(x->word);
#ifdef oldandslow
	  free(x->ip);
	  free(x->port);
	  free(x->timestamp);
#endif
	}
#ifndef oldandslow
	/* reduce allocations */
	x->word=allocassert(malloc((fields[4]-fields[1])+(fields[0]-line)));
	memcpy(x->word,fields[1],fields[4]-fields[1]);
	x->ip=x->word+(fields[2]-fields[1]);
	x->port=x->ip+(fields[3]-fields[2]);
	x->timestamp=x->port+(fields[4]-fields[3]);
	memcpy(x->timestamp,line,fields[0]-line);
#else
	x->word=allocassert(strdup(fields[1]));
	x->ip=allocassert(strdup(fields[2]));
	x->port=allocassert(strdup(fields[3]));
	x->timestamp=allocassert(strdup(line));
#endif
      } else if (!strncmp(fields[0],"close/",6)) {
	struct node** N;
	N=lookup(fields[1]);
	if (*N) {
	  struct node* y=(*N)->next;
	  struct node* x=*N;
	  free(x->word);
#ifdef oldandslow
	  free(x->ip);
	  free(x->port);
	  free(x->timestamp);
#endif
	  free(x);
	  *N=y;
	}
      } else if (cmp3(fields[0],"GET") || cmp4(fields[0],"POST") || cmp4(fields[0],"HEAD")) {
	if (i>6) {	/* otherwise it's a format violation and we ignore the line */
	  struct node** N;
	  N=lookup(fields[1]);
#ifdef oldandslow
	  printf("%s %s %s http%s://%s%s %s %s %s\n",
		 timestamp,fields[0],*N?(*N)->ip:"::",
		 strstr(fields[0],"SSL")?"s":"",fields[6],fields[2],fields[3],fields[4],fields[5]);
#else
	  buffer_putm(buffer_1,timestamp," ",fields[0]," ",*N?(*N)->ip:"::"," http",
		      strstr(fields[0],"SSL")?"s":"","://",fields[6],fields[2]," ",
		      fields[3]," ",fields[4]," ",fields[5],"\n");
#endif
	}
      }
    }
  }
#ifndef oldandslow
  buffer_flush(buffer_1);
#endif
  return 0;
}