Esempio n. 1
0
void read_binary_file(char* file){
    unsigned i;
    unsigned magic;

    fprintf(stderr, "\n\nReading Binary File...\n");
    puts(file);

    FILE *fp;
    fp = fopen(file, "rb");

    if(fp == NULL){
        fprintf(stderr, "Error: Cannot read bonare file \n");
        exit(-1);
    }

    fread(&magic, sizeof(unsigned), 1, fp);

    read_const_tables(fp);

    fread(&currInstruction, sizeof(unsigned), 1, fp);
    currInstruction++;
    instructions = (struct instruction*)malloc((currInstruction+5)*sizeof(struct instruction));
    for(i=1; i<currInstruction; i++){
        read_instruction(fp, &instructions[i]);
    }

    fclose(fp);

    fprintf(stderr, "Done reading Binary File...\n");
}
Esempio n. 2
0
File: parse.c Progetto: rioki/d16
void read_program()
{
    while (token != EOF_TOKEN)
    {
        read_instruction();
    }
}
Esempio n. 3
0
void AssemblerY86::readFile(std::string file_name)
{
    std::ifstream fin(file_name.c_str());
    while (!fin.eof()) {
        read_instruction(fin,InstructionRegister);
    }
    InstructionRegister.pop_back();
    fin.close();
}
Esempio n. 4
0
proc_inst_t& getInstruction(uint64_t ino, bool& success){
    while(instruction_list.size()<ino){
        proc_inst_t tmp;
    	memset(&tmp, 0, sizeof(proc_inst_t));
        if(read_instruction(&tmp)){
            instruction_list.push_back(tmp);
        } else {
            success = false;
            return instruction_list[0];
        }
    }
    success = true;
    return instruction_list[ino-1]; // instructions are 1 indexed, the vector is 0 indexed.
}
Esempio n. 5
0
void execute_vm(struct lilith* vm)
{
	struct Instruction* current;
	current = calloc(1, sizeof(struct Instruction));

	while(!vm->halted)
	{
		read_instruction(vm, current);
		eval_instruction(vm, current);
	}

	free(current);
	return;
}
int main(int argc, char **argv) {
  command cmd = {' ', -1, -1, 0};
  in = open(argv[1],O_RDONLY);
  if(in < 0) {
    perror("Error open");
    exit(EXIT_FAILURE);
  }
  out = open(argv[2], O_RDWR | O_TRUNC | O_CREAT, 0644);
  if(out < 0) {
    perror("Error open");
    exit(EXIT_FAILURE);
  }
  do {
    read_instruction(&cmd);
    interpret_instruction(&cmd);
  }while(!exit_ed(&cmd));
  return 0;
}
int main(int argc, char **argv) {

    if(argc < 3) {
      exit(EXIT_FAILURE);  
    }

    int fd_in  = open(argv[1], O_RDONLY);
    int fd_out = open(argv[2], O_WRONLY|O_CREAT, 0664);
    int continue_edition = 1;
    int error = 0;
    int result = 0;

    int cur_line = 0;
    char buf[SIZE] = {'\0'};
   
    do {
        result = read_instruction(buf);
        if(result > 0) {
            result = interpret_instruction(buf, fd_in, cur_line, fd_out);
            if(result == -1) {
                continue_edition = 0;
            }
            else if(result == -2) {
                printf("ERROR\n");
                error = 1;
                continue_edition = 0;
            }
        }
        else {
            error = 1;
            continue_edition = 0;    
        }

    }while(continue_edition);

    close(fd_in);
    close(fd_out); 

    if(error)
        exit(EXIT_FAILURE);
    else
        exit(EXIT_SUCCESS);

}
Esempio n. 8
0
VALUE
ox_parse(char *xml, ParseCallbacks pcb, char **endp, int trace, Effort effort) {
    struct _PInfo	pi;
    int			body_read = 0;

    if (0 == xml) {
	raise_error("Invalid arg, xml string can not be null", xml, 0);
    }
    if (DEBUG <= trace) {
	printf("Parsing xml:\n%s\n", xml);
    }
    /* initialize parse info */
    pi.str = xml;
    pi.s = xml;
    pi.h = 0;
    pi.pcb = pcb;
    pi.obj = Qnil;
    pi.circ_array = 0;
    pi.encoding = 0;
    pi.trace = trace;
    pi.effort = effort;
    while (1) {
	next_non_white(&pi);	// skip white space
	if ('\0' == *pi.s) {
	    break;
	}
	if (body_read && 0 != endp) {
	    *endp = pi.s;
	    break;
	}
	if ('<' != *pi.s) {		// all top level entities start with <
	    raise_error("invalid format, expected <", pi.str, pi.s);
	}
	pi.s++;		// past <
	switch (*pi.s) {
	case '?':	// prolog
	    pi.s++;
	    read_instruction(&pi);
	    break;
	case '!':	/* comment or doctype */
	    pi.s++;
	    if ('\0' == *pi.s) {
		raise_error("invalid format, DOCTYPE or comment not terminated", pi.str, pi.s);
	    } else if ('-' == *pi.s) {
		pi.s++;	// skip -
		if ('-' != *pi.s) {
		    raise_error("invalid format, bad comment format", pi.str, pi.s);
		} else {
		    pi.s++;	// skip second -
		    read_comment(&pi);
		}
	    } else if (0 == strncmp("DOCTYPE", pi.s, 7)) {
		pi.s += 7;
		read_doctype(&pi);
	    } else {
		raise_error("invalid format, DOCTYPE or comment expected", pi.str, pi.s);
	    }
	    break;
	case '\0':
	    raise_error("invalid format, document not terminated", pi.str, pi.s);
	default:
	    read_element(&pi);
	    body_read = 1;
	    break;
	}
    }
    return pi.obj;
}
Esempio n. 9
0
int main(int argc, char **argv)
{
    char *trace_file_name;
    int trace_view_on = 0;
    int branch_prediction_method = 0;
    unsigned int cycle_number = 0;

    // Parse Inputs
    if (argc == 2) {
        trace_file_name = argv[1];
        trace_view_on = 0;
        branch_prediction_method = 0;       
    } else if (argc == 4) {
        trace_file_name = argv[1];
        trace_view_on = atoi(argv[2]);
        branch_prediction_method = (atoi(argv[3]) == 1) ? 1 : 0;
    } else {
        fprintf(stdout, "\nUSAGE: tv <trace_file> <switch - any character> <branch_prediction - 0|1>\n");
        fprintf(stdout, "\n(switch) to turn on or off individual item view.\n");
        fprintf(stdout, "(branch_prediction) sets the branch prediction method as \'assume not taken\' (0), or a 1-bit branch predictor (1)\n\n");
        exit(0);
    }

    // debug - print parsed options
    char dbg_msg[200];
    sprintf(dbg_msg,
            "\n-debug- parsed inputs. file=%s, view_trace=%d, branch_pred=%d\n",
            trace_file_name,
            (trace_view_on == 0) ? 0 : 1,
            (branch_prediction_method == 0) ? 0 : 1
           );
    debug_print(dbg_msg);

    // Open the trace file.
    fprintf(stdout, "\n ** opening file %s\n", trace_file_name);
    trace_fd = fopen(trace_file_name, "rb");
    if (!trace_fd) {
        fprintf(stdout, "\ntrace file %s not opened.\n\n", trace_file_name);
        exit(0);
    }

    trace_init();

    // store what instruction is in each stage of the pipeline (can be no-ops)
    struct trace_item new_instruction;
    struct trace_item if_stage;
    struct trace_item id_stage;
    struct trace_item ex_stage;
    struct trace_item mem_stage;
    struct trace_item wb_stage;
    zero_buf(&new_instruction);
    zero_buf(&if_stage);
    zero_buf(&id_stage);
    zero_buf(&ex_stage);
    zero_buf(&mem_stage);
    zero_buf(&wb_stage);
    memset(&btb_table, 0, sizeof(short) * BTB_ENTRIES);

    int instructions_left = 5;  
    while(instructions_left) {
        cycle_number++;

        if(trace_view_on) { 
            print_finished_instruction(&wb_stage, cycle_number);
        }

        int hazard = 0;

        //detection of non-happy
        if(branch_prediction_method == 0 && ex_stage.type == ti_BRANCH){
            if(ex_stage.PC + 4 != id_stage.PC){
                hazard = 2; //incorrect no prediction
                debug_print("[HAZARD] Incorrect default (not taken) prediciton\n");
            }
        }
        else if(ex_stage.type == ti_JTYPE|| ex_stage.type == ti_JRTYPE){
            hazard = 2;  //jump
            debug_print("[HAZARD] jump\n");
        }
        else if(branch_prediction_method == 1 && ex_stage.type == ti_BRANCH){
            if(ex_stage.PC +4 == id_stage.PC){ // not taken
                if(get_btb_value(ex_stage.PC) == 1){ //predict taken
                    hazard = 2; //branch
                    debug_print("[HAZARD] predicted taken when not taken\n");
                    set_btb_value(ex_stage.PC, 0);
                }
            }
            else{ //taken
                if(get_btb_value(ex_stage.PC) == 0){ //predict not taken
                    hazard = 2; //branch
                    debug_print("[HAZARD] predicted not taken when taken\n");
                    set_btb_value(ex_stage.PC, 1);
                }
            }
        }
        else if(ex_stage.type == ti_LOAD){
            if(ex_stage.dReg == id_stage.sReg_a || ex_stage.dReg == id_stage.sReg_b){
                hazard = 1;  //forward
                debug_print("[HAZARD] forward\n");
            }
        }


        wb_stage  = mem_stage;
        mem_stage = ex_stage; 

        switch(hazard) {
            case 0: //happy path
                ex_stage = id_stage;
                id_stage = if_stage;
                if(!read_instruction(&if_stage)) {
                    instructions_left--;
                    zero_buf(&if_stage);
                }
                break;

            case 1: //forward
                zero_buf(&ex_stage); 
                break;

            case 2: //branch resolve/jump resolve
                add_queued_instruction(&id_stage);
                add_queued_instruction(&if_stage);
                zero_buf(&id_stage);
                zero_buf(&if_stage);  
                ex_stage = id_stage;
                id_stage = if_stage;
                if(!read_instruction(&if_stage)) {
                    instructions_left--;
                    zero_buf(&if_stage);
                }
                break;

            default:
                printf("f**k.\n");
                exit(1);
        }
    }

    printf("+ Simulation terminates at cycle : %u\n", cycle_number); 

    trace_uninit();

    exit(0);
}
Esempio n. 10
0
static void
parse(SaxDrive dr) {
    char        c = skipBOM(dr);
    int		state = START_STATE;

    while ('\0' != c) {
	buf_protect(&dr->buf);
        if (is_white(c) && '\0' == (c = buf_next_non_white(&dr->buf))) {
            break;
        }
	if ('<' == c) {
	    c = buf_get(&dr->buf);
	    switch (c) {
	    case '?': /* instructions (xml or otherwise) */
		c = read_instruction(dr);
		break;
	    case '!': /* comment or doctype */
		buf_protect(&dr->buf);
		c = buf_get(&dr->buf);
		if ('\0' == c) {
		    ox_sax_drive_error(dr, NO_TERM "DOCTYPE or comment not terminated");
		    goto DONE;
		} else if ('-' == c) {
		    c = buf_get(&dr->buf); /* skip first - and get next character */
		    if ('-' != c) {
			ox_sax_drive_error(dr, INVALID_FORMAT "bad comment format, expected <!--");
		    } else {
			c = buf_get(&dr->buf); /* skip second - */
		    }
		    c = read_comment(dr);
		} else {
		    int	i;
		    int	spaced = 0;
		    int	line = dr->buf.line;
		    int	col = dr->buf.col;

		    if (is_white(c)) {
			spaced = 1;
			c = buf_next_non_white(&dr->buf);
		    }
		    dr->buf.str = dr->buf.tail - 1;
		    for (i = 7; 0 < i; i--) {
			c = buf_get(&dr->buf);
		    }
		    if (0 == strncmp("DOCTYPE", dr->buf.str, 7)) {
			if (spaced) {
			    ox_sax_drive_error_at(dr, WRONG_CHAR "<!DOCTYPE can not included spaces", line, col);
			}
			if (START_STATE != state) {
			    ox_sax_drive_error(dr, OUT_OF_ORDER "DOCTYPE can not come after an element");
			}
			c = read_doctype(dr);
		    } else if (0 == strncasecmp("DOCTYPE", dr->buf.str, 7)) {
			ox_sax_drive_error(dr, CASE_ERROR "expected DOCTYPE all in caps");
			if (START_STATE != state) {
			    ox_sax_drive_error(dr, OUT_OF_ORDER "DOCTYPE can not come after an element");
			}
			c = read_doctype(dr);
		    } else if (0 == strncmp("[CDATA[", dr->buf.str, 7)) {
			if (spaced) {
			    ox_sax_drive_error_at(dr, WRONG_CHAR "<![CDATA[ can not included spaces", line, col);
			}
			c = read_cdata(dr);
		    } else if (0 == strncasecmp("[CDATA[", dr->buf.str, 7)) {
			ox_sax_drive_error(dr, CASE_ERROR "expected CDATA all in caps");
			c = read_cdata(dr);
		    } else {
			ox_sax_drive_error_at(dr, WRONG_CHAR "DOCTYPE, CDATA, or comment expected", line, col);
			c = read_name_token(dr);
			if ('>' == c) {
			    c = buf_get(&dr->buf);
			}
		    }
		}
		break;
	    case '/': /* element end */
		c = read_element_end(dr);
		if (0 == stack_peek(&dr->stack)) {
		    state = AFTER_STATE;
		}
		break;
	    case '\0':
		goto DONE;
	    default:
		buf_backup(&dr->buf);
		if (AFTER_STATE == state) {
		    ox_sax_drive_error(dr, OUT_OF_ORDER "multiple top level elements");
		}
		state = BODY_STATE;
		c = read_element_start(dr);
		if (0 == stack_peek(&dr->stack)) {
		    state = AFTER_STATE;
		}
		break;
	    }
	} else {
	    buf_reset(&dr->buf);
	    c = read_text(dr);
	}
    }
 DONE:
    if (dr->stack.head < dr->stack.tail) {
	char	msg[256];
	Nv	sp;

	if (dr->has.line) {
	    rb_ivar_set(dr->handler, ox_at_line_id, LONG2NUM(dr->buf.line));
	}
	if (dr->has.column) {
	    rb_ivar_set(dr->handler, ox_at_column_id, LONG2NUM(dr->buf.col));
	}
	for (sp = dr->stack.tail - 1; dr->stack.head <= sp; sp--) {
	    snprintf(msg, sizeof(msg) - 1, "%selement '%s' not closed", EL_MISMATCH, sp->name);
	    ox_sax_drive_error_at(dr, msg, dr->buf.line, dr->buf.col);
	    if (dr->has.end_element) {
		VALUE       args[1];

		args[0] = sp->val;
		rb_funcall2(dr->handler, ox_end_element_id, 1, args);
	    }
        }
    }
}
Esempio n. 11
0
static bool arm_unwind(struct unwind_regs *frame, bool *sp_modified, unsigned int depth)
{
	u32 fp, sp, pc, lr;
	u32 cur;
	int count = 0;

	pc = frame->pc;
	sp = frame->sp;
	fp = frame->fp;
	lr = frame->lr;

	//cur = pc + arm_inst_size();
	cur = pc;

	*sp_modified = false;

	while (true)
	{
		u32 instr;

		//if (!read_instruction(cur, &instr, 1, false))
		if (!read_instruction(cur, &instr, NULL))
		{
			return false;
		}

		if (count++ >= 0xffff)
		{
			return false;
		}

		if (ADD_SP_SP_immed_INSTR(instr))               // ADD SP, SP #immed
		{
			u8 shifter_operand;

			shifter_operand = get_immed_operand_for_data_proc_instr(instr);

			sp += shifter_operand;

			*sp_modified = true;
		}
		else if (LDMIA_1_SPBASE_INSTR(instr))                 // LDMIA SP{!}, {Rx, ..., Ry}
		{
			int i;
			u32 regs[16];
			bool update_base_reg;
			u32 address;

			memset(regs, 0, sizeof(regs));

			update_base_reg = ldm_stm_inst_update_base_reg(instr);

			address = sp;

			for (i=0; i<=15; i++)
			{
				if (instr & (1 << i))
				{
					if (!read_data_from_addr(address, &regs[i], arm_inst_size()))
					{
						return false;
					}

					address += arm_inst_size();
				}
			}

			if (update_base_reg)                // SP is base register and will be updated
			{
				sp += px_get_bit_count(instr & 0xffff) * arm_inst_size();
				*sp_modified = true;
			}

			if (instr & (1 << 11))
			{
				fp = regs[11];
			}

			if (instr & (1 << 13))
			{
				sp = regs[13];
				*sp_modified = true;
			}

			if (instr & (1 << 14))
			{
				lr = regs[14];
			}

			if (instr & (1 << 15))
			{
				pc = regs[15];
				break;
			}

		}
		else if (SUB_SP_SP_immed_INSTR(instr))           // SUB   SP, SP, #immed
		{
			u8 shifter_operand;

			shifter_operand = get_immed_operand_for_data_proc_instr(instr);

			sp -= shifter_operand;

			*sp_modified = true;

			//pc = frame->lr;
		}
		else if (STMDB_1_SPBASE_INSTR(instr))                  // STMDB SP!, {Rx, ..., Ry}
		{
			sp -= px_get_bit_count(instr & 0xffff) * arm_inst_size();
			*sp_modified = true;
			//pc = frame->lr;
		}
		else if (SUB_SP_FP_immed_INSTR(instr))           // SUB SP, FP, #immed
		{
			u8 shifter_operand;

			shifter_operand = get_immed_operand_for_data_proc_instr(instr);

			sp = fp - shifter_operand;
			*sp_modified = true;
		}
		else if (ADD_SP_FP_immed_INSTR(instr))           // ADD SP, FP, #immed
		{
			u8 shifter_operand;

			shifter_operand = get_immed_operand_for_data_proc_instr(instr);

			sp = fp + shifter_operand;
			*sp_modified = true;
		}
		else if (LDR_LR_SPBASE_immed_INSTR(instr))       // LDR lr, [sp, #immed]
		{
			u16 immed;

			immed = instr & 0xfff;

			if (!read_data_from_addr(sp + immed, &lr, arm_inst_size()))
			{
				return false;
			}

		}
		else if (LDR_FP_SPBASE_immed_INSTR(instr))       // LDR fp, [sp, #immed]
		{
			u16 immed;

			immed = instr & 0xfff;

			if (!read_data_from_addr(sp + immed, &fp, arm_inst_size()))
			{
				return false;
			}
		}
		else if (LDR_LR_SPBASE_immed_pre_INSTR(instr))  // LDR lr, [sp, #immed]!
		{
			u16 immed;

			immed = instr & 0xfff;

			sp += immed;
			*sp_modified = true;

			if (!read_data_from_addr(sp, &lr, arm_inst_size()))
			{
				return false;
			}
		}
		else if (LDR_FP_SPBASE_immed_pre_INSTR(instr))  // LDR fp, [sp, #immed]!
		{
			u16 immed;

			immed = instr & 0xfff;

			sp += immed;
			*sp_modified = true;

			if (!read_data_from_addr(sp, &fp, arm_inst_size()))
			{
				return false;
			}
		}
		else if (LDR_LR_SPBASE_immed_post_INSTR(instr))  // LDR lr, [sp], #immed
		{
			u16 immed;

			immed = instr & 0xfff;

			if (!read_data_from_addr(sp, &lr, arm_inst_size()))
			{
				return false;
			}

			sp += immed;
			*sp_modified = true;
		}
		else if (LDR_FP_SPBASE_immed_post_INSTR(instr))  // LDR fp, [sp], #immed
		{
			u16 immed;

			immed = instr & 0xfff;

			if (!read_data_from_addr(sp, &fp, arm_inst_size()))
			{
				return false;
			}

			sp += immed;
			*sp_modified = true;
		}
		else if (BX_LR_INSTR(instr))                     // BX lr
		{
			pc = lr;

			break;
		}
		else if (MOV_PC_LR(instr))                       // MOV  PC, LR
		{
			pc = lr;
			break;
		}

		cur += arm_inst_size();
	}

	frame->pc = pc;
	frame->sp = sp;
	frame->fp = fp;

	return true;
}
Esempio n. 12
0
static bool thumb_unwind(struct unwind_regs *frame, bool *sp_modified, unsigned int depth)
{
	u32 pc, sp, fp, lr;
	u32 cur;

	u32 reg_data[16];
	int count;
	unsigned int inst_size;
	u32 inst;
	struct unwind_regs regs;

	pc = frame->pc;
	sp = frame->sp;
	fp = frame->fp;
	lr = frame->lr;

	count = 0;

	*sp_modified = false;
/*
	if (!read_instruction(pc, &inst, &inst_size))
	{
		return false;
	}

	cur = pc + inst_size;
*/
	cur = pc;

	memcpy(&regs, frame, sizeof(struct unwind_regs));

	while (true)
	{
		u32 old_sp;
		bool continue_emul;

		if (!read_instruction(cur, &inst, &inst_size))
		{
			return false;
		}

		if (count++ >= 0xffff)
		{
			return false;
		}

		old_sp = sp;

		if (inst_size == THUMB16_INST_SIZE)
		{
			continue_emul = thumb16_unwind_emul_one_inst(inst, &regs, reg_data);
		}
		else
		{
			continue_emul = thumb32_unwind_emul_one_inst(inst, &regs, reg_data);
		}

		if (regs.sp != old_sp)
		{
			*sp_modified = true;
		}

		if (!continue_emul)
			break;

		cur += inst_size;
	}

	frame->pc = pc;
	frame->sp = sp;
	frame->fp = fp;

	return true;
}
Esempio n. 13
0
File: parse.c Progetto: phlipper/ox
/* Entered after the '<' and the first character after that. Returns status
 * code.
 */
static void
read_element(PInfo pi) {
    struct _Attr	attrs[MAX_ATTRS];
    Attr		ap = attrs;
    char		*name;
    char		*ename;
    char		*end;
    char		c;
    long		elen;
    int			hasChildren = 0;
    int			done = 0;

    ename = read_name_token(pi);
    end = pi->s;
    elen = end - ename;
    next_non_white(pi);
    c = *pi->s;
    *end = '\0';
    if ('/' == c) {
	/* empty element, no attributes and no children */
	pi->s++;
	if ('>' != *pi->s) {
	    /*printf("*** '%s' ***\n", pi->s); */
	    raise_error("invalid format, element not closed", pi->str, pi->s);
	}
	pi->s++;	/* past > */
	ap->name = 0;
	pi->pcb->add_element(pi, ename, attrs, hasChildren);
	pi->pcb->end_element(pi, ename);

	return;
    }
    /* read attribute names until the close (/ or >) is reached */
    while (!done) {
	if ('\0' == c) {
	    next_non_white(pi);
	    c = *pi->s;
	}
	switch (c) {
	case '\0':
	    raise_error("invalid format, document not terminated", pi->str, pi->s);
	case '/':
	    /* Element with just attributes. */
	    pi->s++;
	    if ('>' != *pi->s) {
		raise_error("invalid format, element not closed", pi->str, pi->s);
	    }
	    pi->s++;
	    ap->name = 0;
	    pi->pcb->add_element(pi, ename, attrs, hasChildren);
	    pi->pcb->end_element(pi, ename);

	    return;
	case '>':
	    /* has either children or a value */
	    pi->s++;
	    hasChildren = 1;
	    done = 1;
	    ap->name = 0;
	    pi->pcb->add_element(pi, ename, attrs, hasChildren);
	    break;
	default:
	    /* Attribute name so it's an element and the attribute will be */
	    /* added to it. */
	    ap->name = read_name_token(pi);
	    end = pi->s;
	    next_non_white(pi);
	    if ('=' != *pi->s++) {
		raise_error("invalid format, no attribute value", pi->str, pi->s);
	    }
	    *end = '\0'; /* terminate name */
	    /* read value */
	    next_non_white(pi);
	    ap->value = read_quoted_value(pi);
	    if (0 != strchr(ap->value, '&')) {
		if (0 != collapse_special(pi, (char*)ap->value)) {
		    raise_error("invalid format, special character does not end with a semicolon", pi->str, pi->s);
		}
	    }
	    ap++;
	    if (MAX_ATTRS <= (ap - attrs)) {
		raise_error("too many attributes", pi->str, pi->s);
	    }
	    break;
	}
	c = '\0';
    }
    if (hasChildren) {
	char	*start;
	int	first = 1;
	
	done = 0;
	/* read children */
	while (!done) {
	    start = pi->s;
	    next_non_white(pi);
	    c = *pi->s++;
	    if ('\0' == c) {
		raise_error("invalid format, document not terminated", pi->str, pi->s);
	    }
	    if ('<' == c) {
		char	*slash;

		switch (*pi->s) {
		case '!':	/* better be a comment or CDATA */
		    pi->s++;
		    if ('-' == *pi->s && '-' == *(pi->s + 1)) {
			pi->s += 2;
			read_comment(pi);
		    } else if (0 == strncmp("[CDATA[", pi->s, 7)) {
			pi->s += 7;
			read_cdata(pi);
		    } else {
			raise_error("invalid format, invalid comment or CDATA format", pi->str, pi->s);
		    }
		    break;
		case '?':	/* processing instruction */
		    pi->s++;
		    read_instruction(pi);
		    break;
		case '/':
		    slash = pi->s;
		    pi->s++;
		    name = read_name_token(pi);
		    end = pi->s;
		    next_non_white(pi);
		    c = *pi->s;
		    *end = '\0';
		    if (0 != strcmp(name, ename)) {
			raise_error("invalid format, elements overlap", pi->str, pi->s);
		    }
		    if ('>' != c) {
			raise_error("invalid format, element not closed", pi->str, pi->s);
		    }
		    if (first && start != slash - 1) {
			/* some white space between start and here so add as text */
			*(slash - 1) = '\0';
			pi->pcb->add_text(pi, start, 1);
		    }
		    pi->s++;
		    pi->pcb->end_element(pi, ename);
		    return;
		case '\0':
		    raise_error("invalid format, document not terminated", pi->str, pi->s);
		default:
		    first = 0;
		    /* a child element */
		    read_element(pi);
		    break;
		}
	    } else {	/* read as TEXT */
		pi->s = start;
		/*pi->s--; */
		read_text(pi);
		/*read_reduced_text(pi); */

		/* to exit read_text with no errors the next character must be < */
		if ('/' == *(pi->s + 1) &&
		    0 == strncmp(ename, pi->s + 2, elen) &&
		    '>' == *(pi->s + elen + 2)) {
		    /* close tag after text so treat as a value */
		    pi->s += elen + 3;
		    pi->pcb->end_element(pi, ename);
		    return;
		}
	    }
	}
    }
}