Beispiel #1
0
// Bind image even if nobind active (i.e. for uploading image)
void GL_BindForce(const image_t *tex)
{
	int tmu = gl_state.currentTmu;

	if (gl_state.textureTarget[tmu] != tex->target)
	{
		if (gl_state.textureTarget[tmu])
			glDisable(gl_state.textureTarget[tmu]);
		glEnable(tex->target);
		gl_state.textureTarget[tmu] = tex->target;
	}

	if (gl_state.currentBinds[tmu] == tex) return;

	gl_state.currentBinds[tmu] = tex;
	LOG_STRING(va("// GL_Bind(%s)", *tex->Name));
	glBindTexture(tex->target, tex->texnum);
#if MAX_DEBUG
	GLenum err = glGetError();
	if (err) appWPrintf("BindForce: error with %s\n", *tex->Name);
#endif
	STAT(gl_stats.numBinds++);
}
// Allocates a new env and loads the named user program into it.
struct Env* env_create(char* user_program_name, unsigned int page_WS_size)
{
	//[1] get pointer to the start of the "user_program_name" program in memory
	// Hint: use "get_user_program_info" function,
	// you should set the following "ptr_program_start" by the start address of the user program
	uint8* ptr_program_start = 0;

	struct UserProgramInfo* ptr_user_program_info = get_user_program_info(user_program_name);
	if(ptr_user_program_info == 0) return NULL;
	ptr_program_start = ptr_user_program_info->ptr_start ;
	//	if(ptr_user_program_info->environment != NULL)
	//	{
	//		cprintf("env_create: an old environment already exist for [%s]!! \nfreeing the old one by calling start_env_free....\n", ptr_user_program_info->environment->prog_name);
	//		start_env_free(ptr_user_program_info->environment);
	//
	//		//return ptr_user_program_info;
	//	}


	//[2] allocate new environment, (from the free environment list)
	//if there's no one, return NULL
	// Hint: use "allocate_environment" function
	struct Env* e = NULL;
	if(allocate_environment(&e) < 0)
	{
		return 0;
	}

	//[2.5 - 2012] Set program name inside the environment
	e->prog_name = ptr_user_program_info->name ;

	//[3] allocate a frame for the page directory, Don't forget to set the references of the allocated frame.
	//REMEMBER: "allocate_frame" should always return a free frame
	uint32* ptr_user_page_directory;
	unsigned int phys_user_page_directory;
	if(USE_KHEAP)
	{
		ptr_user_page_directory = create_user_directory();
		phys_user_page_directory = kheap_physical_address((uint32)ptr_user_page_directory);
	}
	else
	{
		int r;
		struct Frame_Info *p = NULL;

		allocate_frame(&p) ;
		p->references = 1;

		ptr_user_page_directory = STATIC_KERNEL_VIRTUAL_ADDRESS(to_physical_address(p));
		phys_user_page_directory = to_physical_address(p);
	}

	//[4] initialize the new environment by the virtual address of the page directory
	// Hint: use "initialize_environment" function

	//2016
	e->page_WS_max_size = page_WS_size;

	initialize_environment(e, ptr_user_page_directory, phys_user_page_directory);

	// We want to load the program into the user virtual space
	// each program is constructed from one or more segments,
	// each segment has the following information grouped in "struct ProgramSegment"
	//	1- uint8 *ptr_start: 	start address of this segment in memory
	//	2- uint32 size_in_file: size occupied by this segment inside the program file,
	//	3- uint32 size_in_memory: actual size required by this segment in memory
	// 	usually size_in_file < or = size_in_memory
	//	4- uint8 *virtual_address: start virtual address that this segment should be copied to it

	//[6] switch to user page directory
	// Hint: use rcr3() and lcr3()
	uint32 kern_phys_pgdir = rcr3() ;
	lcr3(e->env_cr3) ;

	//[7] load each program segment into user virtual space
	struct ProgramSegment* seg = NULL;  //use inside PROGRAM_SEGMENT_FOREACH as current segment information
	int segment_counter=0;
	uint32 remaining_ws_pages = (e->page_WS_max_size)-1; // we are reserving 1 page of WS for the stack that will be allocated just before the end of this function
	uint32 lastTableNumber=0xffffffff;

	PROGRAM_SEGMENT_FOREACH(seg, ptr_program_start)
	{
		segment_counter++;
		//allocate space for current program segment and map it at seg->virtual_address then copy its content
		// from seg->ptr_start to seg->virtual_address
		//Hint: use program_segment_alloc_map_copy_workingset()

		//cprintf("SEGMENT #%d, dest start va = %x, dest end va = %x\n",segment_counter, seg->virtual_address, (seg->virtual_address + seg->size_in_memory));
		LOG_STRING("===============================================================================");
		LOG_STATMENT(cprintf("SEGMENT #%d, size_in_file = %d, size_in_memory= %d, dest va = %x",segment_counter,seg->size_in_file,
				seg->size_in_memory, seg->virtual_address));
		LOG_STRING("===============================================================================");

		uint32 allocated_pages=0;
		program_segment_alloc_map_copy_workingset(e, seg, &allocated_pages, remaining_ws_pages, &lastTableNumber);

		remaining_ws_pages -= allocated_pages;
		LOG_STATMENT(cprintf("SEGMENT: allocated pages in WS = %d",allocated_pages));
		LOG_STATMENT(cprintf("SEGMENT: remaining WS pages after allocation = %d",remaining_ws_pages));


		///[1] temporary initialize 1st page in memory then writing it on page file
		uint32 dataSrc_va = (uint32) seg->ptr_start;
		uint32 seg_va = (uint32) seg->virtual_address ;

		uint32 start_first_page = ROUNDDOWN(seg_va , PAGE_SIZE);
		uint32 end_first_page = ROUNDUP(seg_va , PAGE_SIZE);
		uint32 offset_first_page = seg_va  - start_first_page ;

		memset(ptr_temp_page , 0, PAGE_SIZE);
		uint8 *src_ptr =  (uint8*) dataSrc_va;
		uint8 *dst_ptr =  (uint8*) (ptr_temp_page + offset_first_page);
		int i;
		for (i = seg_va ; i < end_first_page ; i++, src_ptr++,dst_ptr++ )
		{
			*dst_ptr = *src_ptr ;
		}

		if (pf_add_env_page(e, start_first_page, ptr_temp_page) == E_NO_PAGE_FILE_SPACE)
			panic("ERROR: Page File OUT OF SPACE. can't load the program in Page file!!");

		//LOG_STRING(" -------------------- PAGE FILE: 1st page is written");


		///[2] Start writing the segment ,from 2nd page until before last page, to page file ...

		uint32 start_last_page = ROUNDDOWN(seg_va  + seg->size_in_file, PAGE_SIZE) ;
		uint32 end_last_page = seg_va  + seg->size_in_file;

		for (i = end_first_page ; i < start_last_page ; i+= PAGE_SIZE, src_ptr+= PAGE_SIZE)
		{
			if (pf_add_env_page(e, i, src_ptr) == E_NO_PAGE_FILE_SPACE)
				panic("ERROR: Page File OUT OF SPACE. can't load the program in Page file!!");

		}
		//LOG_STRING(" -------------------- PAGE FILE: 2nd page --> before last page are written");

		///[3] temporary initialize last page in memory then writing it on page file

		dst_ptr =  (uint8*) ptr_temp_page;
		memset(dst_ptr, 0, PAGE_SIZE);

		for (i = start_last_page ; i < end_last_page ; i++, src_ptr++,dst_ptr++ )
		{
			*dst_ptr = *src_ptr;
		}
		if (pf_add_env_page(e, start_last_page, ptr_temp_page) == E_NO_PAGE_FILE_SPACE)
			panic("ERROR: Page File OUT OF SPACE. can't load the program in Page file!!");


		//LOG_STRING(" -------------------- PAGE FILE: last page is written");

		///[4] writing the remaining seg->size_in_memory pages to disk

		uint32 start_remaining_area = ROUNDUP(seg_va + seg->size_in_file,PAGE_SIZE) ;
		uint32 remainingLength = (seg_va + seg->size_in_memory) - start_remaining_area ;

		for (i=0 ; i < ROUNDUP(remainingLength,PAGE_SIZE) ;i+= PAGE_SIZE, start_remaining_area += PAGE_SIZE)
		{
			if (pf_add_empty_env_page(e, start_remaining_area, 1) == E_NO_PAGE_FILE_SPACE)
				panic("ERROR: Page File OUT OF SPACE. can't load the program in Page file!!");
		}
		//LOG_STRING(" -------------------- PAGE FILE: segment remaining area is written (the zeros) ");
	}
//
// Allocate length bytes of physical memory for environment env,
// and map it at virtual address va in the environment's address space.
// Does not zero or otherwise initialize the mapped pages in any way.
// Pages should be writable by user and kernel.
//
// The allocation shouldn't failed
// return 0
//
static int program_segment_alloc_map_copy_workingset(struct Env *e, struct ProgramSegment* seg, uint32* allocated_pages, uint32 remaining_ws_pages, uint32* lastTableNumber)
{
	void *vaddr = seg->virtual_address;
	uint32 length = seg->size_in_memory;

	uint32 end_vaddr = ROUNDUP((uint32)vaddr + length,PAGE_SIZE) ;
	uint32 iVA = ROUNDDOWN((uint32)vaddr,PAGE_SIZE) ;
	int r ;
	uint32 i = 0 ;
	struct Frame_Info *p = NULL;

	*allocated_pages = 0;

	/*2015*/// Load max of 6 pages only for the segment that start with va = 200000 [EXCEPT tpp]
	if (iVA == 0x200000 && strcmp(e->prog_name, "tpp")!=0)
		remaining_ws_pages = remaining_ws_pages < 6 ? remaining_ws_pages:6 ;
	/*==========================================================================================*/
	for (; iVA < end_vaddr && i<remaining_ws_pages; i++, iVA += PAGE_SIZE)
	{
		// Allocate a page
		allocate_frame(&p) ;

		LOG_STRING("segment page allocated");
		loadtime_map_frame(e->env_page_directory, p, (void *)iVA, PERM_USER | PERM_WRITEABLE);
		LOG_STRING("segment page mapped");

		LOG_STATMENT(cprintf("Updating working set entry # %d",e->page_last_WS_index));

		e->ptr_pageWorkingSet[e->page_last_WS_index].virtual_address = iVA;
		e->ptr_pageWorkingSet[e->page_last_WS_index].empty = 0;
		e->ptr_pageWorkingSet[e->page_last_WS_index].time_stamp = 0;

		e->page_last_WS_index ++;
		e->page_last_WS_index %= (e->page_WS_max_size);

		//if a new table is created during the mapping, add it to the table working set
		if(PDX(iVA) != (*lastTableNumber))
		{
			addTableToTableWorkingSet(e, ROUNDDOWN(iVA, PAGE_SIZE*1024));
			if (e->table_last_WS_index == 0)
				panic("\nenv_create: Table working set become FULL during the application loading. Please increase the table working set size to be able to load the program successfully\n");
			(*lastTableNumber) = PDX(iVA);
		}

		/// TAKE CARE !!!! this was an destructive error
		/// DON'T MAKE IT " *allocated_pages ++ " EVER !
		(*allocated_pages) ++;
	}

	uint8 *src_ptr = (uint8 *)(seg->ptr_start) ;
	uint8 *dst_ptr = (uint8 *) seg->virtual_address;

	//copy program segment page from (seg->ptr_start) to (seg->virtual_address)

	LOG_STATMENT(cprintf("copying data to allocated area VA %x from source %x",dst_ptr,src_ptr));
	while((uint32)dst_ptr < (ROUNDDOWN((uint32)vaddr,PAGE_SIZE) + (*allocated_pages)*PAGE_SIZE) &&
			((uint32)dst_ptr< ((uint32)vaddr+ seg->size_in_file)) )
	{
		*dst_ptr = *src_ptr ;
		dst_ptr++ ;
		src_ptr++ ;
	}
	LOG_STRING("zeroing remaining page space");
	while((uint32)dst_ptr < (ROUNDDOWN((uint32)vaddr,PAGE_SIZE) + (*allocated_pages)*PAGE_SIZE) )
	{
		*dst_ptr = 0;
		dst_ptr++ ;
	}

	//============================================

	//	LOG_STRING("creating page tables");
	//	iVA = ROUNDDOWN((uint32)vaddr,PAGE_SIZE) ;
	//	i = 0 ;
	//	for (; iVA < end_vaddr; i++, iVA += PAGE_SIZE)
	//	{
	//		uint32 *ptr_page_table;
	//		get_page_table(e->env_pgdir, (void *)iVA, 1, &ptr_page_table);
	//	}
	//	LOG_STRING("page tables created successfully");
	return 0;
}
bool process_char(char c) {
    bool isDigit = (('0'<=c) && (c<='9'));
    bool isWhite = ((' ' == c)||('\t'==c));
    uint8_t b = 0;

    // ignore '\r'
    if (('\r' == c))
        return TRUE;
    // at end-of-line, command is complete => call process_command
    if (('\n' == c)) {
#ifdef DEBUG
        uint8_t i;
        for(i=0;i<31;i++) {
            if (codes_seen & ((uint32_t)1 << i)) {
                if (numbers_got & ((uint32_t)1 << i)) {
                    LOG_STRING("P: TOKEN ");LOG_CHAR('A'+i);LOG_S32(numbers[i]);LOG_NEWLINE;
                } else {
                    LOG_STRING("P: TOKEN ");LOG_CHAR('A'+i);LOG_NEWLINE;
                }
            }
        }
#endif
        if (base64_len) {
            LOG_STRING("P: TOKEN $ (");LOG_U8(base64_len);LOG_STRING("Bytes)\n");
            // if Stepper queue is empty, transfer modulation data now, else later
            if (STEPPER_QUEUE_is_empty()) {
                for(b=0;b<base64_len;b++)
                    LASER_RASTERDATA_put(base64_bytes[b]);
                base64_len=b=0;
            }
        }
        if (state != ERROR_STATE) {
            LOG_STRING("P: PROCESS COMMAND\n");
            process_command();
            // if stepper queue was not empty before, transfer modulation now
            if(base64_len) {
                for(b=0;b<base64_len;b++)
                    LASER_RASTERDATA_put(base64_bytes[b]);
                base64_len=0;
            }
        } else
            LOG_STRING("P: ERROR-STATE: IGNORE COMMAND!\n");
        // re-init parser
        codes_seen = 0;
        numbers_got = 0;
        state = EXPECT_FIRST_LETTER;
        return state != ERROR_STATE;
    }
    // XXX update checksum

    // state dependent interpretation of characters
    switch(state) {
        case EXPECT_FIRST_LETTER:
            codes_seen = 0;
            numbers_got = 0;
            memset(numbers, 0, sizeof(numbers));
            memset(integers, 0, sizeof(integers));
            memset(base64_bytes, 0, sizeof(base64_bytes));
            memset(filename, 0, sizeof(filename));
            filename_len = 0;
            base64_len = 0;
            state = EXPECT_LETTER;
            // intentionally no break !
        case EXPECT_LETTER:
            if ((('A'<=c) && (c<='Z'))) {
                last_letter = c-'A';
                codes_seen |= ((uint32_t)1) << last_letter;
                state = EXPECT_NUMBER_OR_SIGN;
                return TRUE;
            } else if (isWhite) { // ignore whitespace
                return TRUE;
            } else if ('*' == c) {
                state = PARSE_CHECKSUM;
                return TRUE;
            } else if (';' == c) {
                state = IGNORE_REST;
                return TRUE;
            } else if ('(' == c) {
                state = COMMENT_MODE;
                return TRUE;
            } else if ('$' == c) {
                state = EXPECT_BASE64_1;
                return TRUE;
            } else if ('\'' == c) {
                state = PARSE_FILENAME_TICKS;
                return TRUE;
            } else if ('"' == c) {
                state = PARSE_FILENAME_DOUBLETICKS;
                return TRUE;
            } else if (!filename_len) {
                state = PARSE_FILENAME;
                filename[filename_len++] = c;
                filename[filename_len] = 0;
                return TRUE;
            }
            LOG_PARSE_ERROR("unexpected character and filename already set!");
            break;
        case EXPECT_NUMBER_OR_SIGN:
            if (isWhite) {
                state = EXPECT_LETTER;
                return TRUE;
            } else if (!(isDigit || (c == '+') || (c=='-'))) {
                if (filename_len) {
                    LOG_PARSE_ERROR("filename already set: unexpected character found");
                }
                state = PARSE_FILENAME;
                filename[filename_len++] = last_letter + 'A';
                filename[filename_len++] = c;
                filename[filename_len] = 0;
                return TRUE;
            }
            state = EXPECT_FIRST_DIGIT;
            current_int = 0;
            digits = 0;
            subdigits = 0;
            if (c == '-') {
                isNegative = TRUE;
                return TRUE;
            }
            isNegative = FALSE;
            if (c == '+')    // needless, but valid
                return TRUE;
            // intentionally no break!
        case EXPECT_FIRST_DIGIT:    // first digit of a number
            if (isWhite) {
                state = EXPECT_LETTER;
                return TRUE;
            } else if (!isDigit)
                LOG_PARSE_ERROR("Expected [0-9\\w]");
            current_int = (uint8_t) c - '0';
            digits++;
            state = EXPECT_ANOTHERDIGIT;
            // fall through to number storage
            break;
        case EXPECT_ANOTHERDIGIT: // digits of a number before '.' or 'eE'
            if (isDigit) {
                if (digits>9)
                    LOG_PARSE_ERROR("Too many leading digits!");
                times_ten(current_int);
                current_int += (uint8_t) (c - '0');
                digits++;
                // fall through to number storage
                break;
            } else if ('.' == c) {
                state = EXPECT_SUBDIGITS;
                break;
            } else if (isWhite) {
                state = EXPECT_LETTER;
                break;
            } else if ('*' == c) {
                state = PARSE_CHECKSUM;
                break;
            } else if (';' == c) {
                state = IGNORE_REST;
                break;
            } else if ('(' == c) {
                state = COMMENT_MODE;
                break;
            } else if ('$' == c) {
                state = EXPECT_BASE64_1;
                break;
            } else if ('\'' == c) {
                state = PARSE_FILENAME_TICKS;
                break;
            } else if ('"' == c) {
                state = PARSE_FILENAME_DOUBLETICKS;
                break;
            } else
                LOG_PARSE_ERROR("Expected [0-9.\\w]");

        case EXPECT_SUBDIGITS:    // digits of a number after '.'
            if (isDigit) {
                if (subdigits >= SCALE_DIGITS) // ignore further digits
                    return TRUE;
                if (digits+subdigits > 9) //capacity exceeded!
                    //~ LOG_PARSE_ERROR("Too many total digits!");
                    return TRUE; // ignore further digits
                times_ten(current_int);
                current_int += (uint8_t) (c - '0');
                subdigits++;
                // fall through to number storage
                break;
            } else if (isWhite) {
                state = EXPECT_LETTER;
                return TRUE;
            } else
                LOG_PARSE_ERROR("Expected [0-9\\w]");
        case EXPECT_BASE64_1:    // expect first char of a base64-string
            if (isWhite) {
                state = EXPECT_LETTER;
                return TRUE;
            }
            b = base64_value(c);
            if (b > 63) {
                state = IGNORE_REST;
                LOG_PARSE_ERROR("Expected a BASE64 character");
            }
            base64_bytes[base64_len] = b<<2;
            state = EXPECT_BASE64_2;
            return TRUE;
        case EXPECT_BASE64_2:    // expect second char of a base64-string
            b = base64_value(c);
            if (b > 63) {
                state = IGNORE_REST;
                LOG_PARSE_ERROR("Expected a BASE64 character");
            }
            base64_bytes[base64_len++] |= (b >> 4);
            if (base64_len >= sizeof(base64_bytes)) {
                state = IGNORE_REST;
                LOG_PARSE_ERROR("Too many Base64 Bytes (Buffer full)");
            }
            base64_bytes[base64_len] = (b << 4);
            state = EXPECT_BASE64_3;
            return TRUE;
        case EXPECT_BASE64_3:    // expect third char of a base64-string (may be '=')
            if ('=' != c) {
                b = base64_value(c);
                if (b > 63) {
                    state = IGNORE_REST;
                    LOG_PARSE_ERROR("Expected a BASE64 character");
                }
                base64_bytes[base64_len++] |= (b >> 2);
                if (base64_len >= sizeof(base64_bytes)) {
                    state = IGNORE_REST;
                    LOG_PARSE_ERROR("Too many Base64 Bytes (Buffer full)");
                }
                base64_bytes[base64_len] = (b << 6);
            }
            state = EXPECT_BASE64_4;
            return TRUE;
        case EXPECT_BASE64_4:    // expect fourth char of a base64-string (may be '=')
            if ('=' != c) {
                b = base64_value(c);
                if (b > 63) {
                    state = IGNORE_REST;
                    LOG_PARSE_ERROR("Expected a BASE64 character");
                }
                base64_bytes[base64_len++] |= b;
                if (base64_len >= sizeof(base64_bytes)) {
                    state = IGNORE_REST;
                    LOG_PARSE_ERROR("Too many Base64 Bytes (Buffer full)");
                }
            }
            state = EXPECT_BASE64_1;
            return TRUE;
        case COMMENT_MODE:    // inside comment mode ()
            // just eat everything between '(' and ')'
            if (c == ')') {
                state = EXPECT_LETTER;
            }
            return TRUE;
        case ERROR_STATE: // after an error, ignore until end of line and do not process_command at eol!
            return FALSE;
        case PARSE_CHECKSUM: // after a '*': parse digits of the checksum (untile end of line)
            // ignored.
        case IGNORE_REST:    // after a ; (comment until end of line)
            // just eat everything after a ';'
            return TRUE;
        case PARSE_FILENAME_DOUBLETICKS: // parse filename inside double ticks ""
            if ('"' == c) {
                state = EXPECT_LETTER;
                return TRUE;
            }
            b = filename_len;
            filename[b++] = c;
            filename[b] = 0;
            filename_len = b;
            return (filename_len < sizeof(filename));
        case PARSE_FILENAME_TICKS: // parse filename inside single ticks ''
            if ('\'' == c) {
                state = EXPECT_LETTER;
                return TRUE;
            }
            b = filename_len;
            filename[b++] = c;
            filename[b] = 0;
            filename_len = b;
            return (filename_len < sizeof(filename));
        case PARSE_FILENAME: // Characters which must be a filename
            if (isWhite) {
                state = EXPECT_LETTER;
                return TRUE;
            }
            b = filename_len;
            filename[b++] = c;
            filename[b] = 0;
            filename_len = b;
            return (filename_len < sizeof(filename));

        default:
            LOG_PARSE_ERROR("Unknown or undefined State");
    }
Beispiel #5
0
int tasks_from_string( const char * buffer )
{

    if (NULL == buffer)
    {
        LOG_STRING("Passing NULL to tasks_from_string");
        return -1;
    }

    TiXmlDocument xdoc;


    if (NULL == xdoc.Parse(buffer))
    {
        LOG_STRING("Failed to parse XML: %s", buffer);
        return -2;
    }

    TiXmlElement * root = xdoc.RootElement();

    if (0 == root)
    {
        LOG_STRING("Failed to find XML root in tasks_from_string");
        return -2;
    }

    if (strcmp(root->Value(), "Tasks") != 0)
    {
        LOG_STRING("Element Tasks is expected, but find : %s", root->Value());
        return -1;
    }

    for (TiXmlElement *task=root->FirstChildElement(); task;
        task = task->NextSiblingElement())
    {
        TaskPtr p = new Task();
        char url[512];


        if (NULL != task->Attribute("from"))
        {
            strcpy(url, task->Attribute("from"));

            LOG_STRING("Before Parsing");

            if (parse_url(url, p->from.ip, & p->from.port))
            {
                LOG_STRING("Failed to parse url : %s", url);
            }

            LOG_STRING("Get %s : %d", p->from.ip, p->from.port);
        }



        p->id = atoi(task->FirstChildElement("id")->FirstChild()->Value());
        strcpy(p->name, task->FirstChildElement("name")->FirstChild()->Value());
        p->sid = atoi(task->FirstChildElement("sid")->FirstChild()->Value());
        strcpy(p->subdir, task->FirstChildElement("subdir")->FirstChild()->Value());


        add_to_queue(p);
    }
    
    if (is_no_task())
    {
        return -3;
    }

    // Update TaskQueue status code
    g_tqs = TQS_PENDING;

    return 0;
}
Beispiel #6
0
static
void
MakeOrderResultPage(OpenSOAPStringHashPtr str) {
	static char FuncName[] = "MakeOrderResultPage";
    int error = OPENSOAP_NO_ERROR;
	
	char *endpoint;
	char *pubKey;
	char *privKey;
	char *spec = NULL;
	const char *manufacture = NULL;
	const char *name = NULL;
	const char *code = NULL;
	const char *price = NULL;
	
	error = OpenSOAPStringHashGetValueMB(str, "endpoint", (void**)&endpoint);
 	DecodeURLEncodedString(&endpoint);
	LOG_STRING(FuncName, "endpoint", endpoint ? endpoint : "(null)");
	
	error = OpenSOAPStringHashGetValueMB(str, "pubKey", (void**)&pubKey);
 	DecodeURLEncodedString(&pubKey);
	LOG_STRING(FuncName, "pubKey", pubKey ? pubKey : "(null)");
	
	error = OpenSOAPStringHashGetValueMB(str, "privKey", (void**)&privKey);
 	DecodeURLEncodedString(&privKey);
	LOG_STRING(FuncName, "privKey", privKey ? privKey : "(null)");
	
	error = OpenSOAPStringHashGetValueMB(str, "spec", (void**)&spec);
	if (OPENSOAP_SUCCEEDED(error)) {
		char *confirmation = NULL;
		char *qty;
		manufacture = strtok(spec, "_");
		name = strtok(NULL, "_");
		code = strtok(NULL, "_");
		price = strtok(NULL, "_");
		
		error = OpenSOAPStringHashGetValueMB(str, "qty", (void**)&qty);
		
		fprintf(stderr,
				"PlaceOrder: %s, %s\n",
				code ? code : "(null)",
				qty);
		
		error = PlaceOrder(endpoint,
						   NULL,
						   DEFAULT_CHARENC,
						   SERVICE_NS_URI,
						   pubKey,
						   privKey,
						   code,
						   atol(qty),
						   &confirmation);
		
		fprintf(stderr,
				"OrderResult: %s\n",
				confirmation ? confirmation : "(null)");
		
		if (confirmation) {
			SendHtmlText("./ShoppingHtml/CommonHdr.html");
			SendHtmlText("./ShoppingHtml/OrderResultHdr.html");
			
			printf("<tr>"
				   "<td>%s</td>"
				   "<td>%s</td>"
				   "<td>%s</td>"
				   "<td align=right>%s</td>"
				   "<td align=right>%s</td>"
				   "<td>%s</td>"
				   "</tr>\n",
				   manufacture,
				   name,
				   code,
				   price,
				   qty,
				   confirmation);
			
			SendHtmlText("./ShoppingHtml/OrderResultFtr.html");
			SendHtmlText("./ShoppingHtml/CommonFtr.html");
			
			free(confirmation);
		}
		else {
			/* error */
			SendHtmlText("./ShoppingHtml/CommonHdr.html");
			SendHtmlText("./ShoppingHtml/OrderResultErr.html");
			SendHtmlText("./ShoppingHtml/CommonFtr.html");
		}
	}
	else {
		/* error */
		SendHtmlText("./ShoppingHtml/CommonHdr.html");
		SendHtmlText("./ShoppingHtml/OrderResultErr.html");
		SendHtmlText("./ShoppingHtml/CommonFtr.html");
	}
}
Beispiel #7
0
static
void
MakePlaceOrderPage(OpenSOAPStringHashPtr str) {
	static char FuncName[] = "MakePlaceOrderPage";
    int error = OPENSOAP_NO_ERROR;
	
	char *endpoint;
	char *pubKey;
	char *privKey;
	char *spec = NULL;
	const char *manifucture = NULL;
	const char *name = NULL;
	const char *code = NULL;
	const char *price = NULL;
	
	fprintf(stderr, "\n---------- MakePlaceOrderPage begin ----------\n");
	
	error = OpenSOAPStringHashGetValueMB(str, "endpoint", (void**)&endpoint);
 	DecodeURLEncodedString(&endpoint);
	LOG_STRING(FuncName, "endpoint", endpoint ? endpoint : "(null)");
	
	error = OpenSOAPStringHashGetValueMB(str, "pubKey", (void**)&pubKey);
 	DecodeURLEncodedString(&pubKey);
	LOG_STRING(FuncName, "pubKey", pubKey ? pubKey : "(null)");
	
	error = OpenSOAPStringHashGetValueMB(str, "privKey", (void**)&privKey);
 	DecodeURLEncodedString(&privKey);
	LOG_STRING(FuncName, "privKey", privKey ? privKey : "(null)");
	
	error = OpenSOAPStringHashGetValueMB(str, "spec", (void**)&spec);
	
	if (OPENSOAP_SUCCEEDED(error)) {
		char *spec_tmp = strdup(spec);
		long qty;
		
		manifucture = strtok(spec_tmp, "_");
		name = strtok(NULL, "_");
		code = strtok(NULL, "_");
		price = strtok(NULL, "_");
		
		error = GetStockQty(endpoint,
							NULL,
							DEFAULT_CHARENC,
							SERVICE_NS_URI,
							code,
							&qty);
		
		fprintf(stderr,
				"GetStockQty: %s, %s, %s, %s, %ld\n",
				manifucture ? manifucture : "(null)",
				name ? name : "(null)",
				code ? code : "(null)",
				price,
				qty);

		if (qty >= 0) {
			SendHtmlText("./ShoppingHtml/CommonHdr.html");
			SendHtmlText("./ShoppingHtml/PlaceOrderHdr.html");

			printf("<input type=\"hidden\" name=\"spec\" value=\"%s\">", spec);

			printf("<tr>"
				   "<td>%s</td>"
				   "<td>%s</td>"
				   "<td>%s</td>"
				   "<td align=right>%s</td>"
				   "<td align=right>%ld</td>"
				   "</tr>\n",
				   manifucture,
				   name,
				   code,
				   price,
				   qty);

			printf("<input type=\"hidden\" name=\"endpoint\" value=\"%s\">\n",
				   endpoint);
			printf("<input type=\"hidden\" name=\"pubKey\" value=\"%s\">\n",
				   pubKey);
			printf("<input type=\"hidden\" name=\"privKey\" value=\"%s\">\n",
				   privKey);
			
			SendHtmlText("./ShoppingHtml/PlaceOrderFtr.html");
			SendHtmlText("./ShoppingHtml/CommonFtr.html");
		}
		else {
			/* error */
			SendHtmlText("./ShoppingHtml/CommonHdr.html");
			SendHtmlText("./ShoppingHtml/PlaceOrderErr.html");
			SendHtmlText("./ShoppingHtml/CommonFtr.html");
		}
	}
	else {
		/* error */
		SendHtmlText("./ShoppingHtml/CommonHdr.html");
		SendHtmlText("./ShoppingHtml/PlaceOrderErr.html");
		SendHtmlText("./ShoppingHtml/CommonFtr.html");
	}
	
	fprintf(stderr, "\n---------- MakePlaceOrderPage end ----------\n");
}
Beispiel #8
0
static
void
MakeGetStockQtyPage(const char* confFile,
					OpenSOAPStringHashPtr str) {
	static char FuncName[] = "MakeGetStockQtyPage";
    int error = OPENSOAP_NO_ERROR;
	
	char *endpoint;
	char *pubKey;
	char *privKey;
	FILE *fp;
	
	ProductListPtr productList;
	
	fprintf(stderr, "\n---------- MakeGetStockQtyPage begin ----------\n");
	
	error = OpenSOAPStringHashGetValueMB(str, "endpoint", (void**)&endpoint);
 	DecodeURLEncodedString(&endpoint);
	LOG_STRING(FuncName, "endpoint", endpoint ? endpoint : "(null)");
	
	error = OpenSOAPStringHashGetValueMB(str, "pubKey", (void**)&pubKey);
 	DecodeURLEncodedString(&pubKey);
	LOG_STRING(FuncName, "pubKey", pubKey ? pubKey : "(null)");
	
	error = OpenSOAPStringHashGetValueMB(str, "privKey", (void**)&privKey);
 	DecodeURLEncodedString(&privKey);
	LOG_STRING(FuncName, "privKey", privKey ? privKey : "(null)");
	
	fprintf(stderr, "confFile = %s\n", confFile);
	fp = fopen(confFile, "w");
	if (!fp) {
		MakeErrorPage("can't open config file for output\n");
	}
	fprintf(fp, "%s\n", endpoint);
	fprintf(fp, "%s\n", pubKey);
	fprintf(fp, "%s\n", privKey);
	fclose(fp);
	
	productList = GetProductList(endpoint,
								 NULL,
								 DEFAULT_CHARENC,
								 SERVICE_NS_URI);
	fprintf(stderr, "GetProductList: %s\n",
			(productList ? "Succeeded" : "Failed"));
	
	if (productList && productList->productCount) {
		ProductListItemPtr products = productList->productList;
		int i = 0;
		
		SendHtmlText("./ShoppingHtml/CommonHdr.html");
		SendHtmlText("./ShoppingHtml/GetStockQtyHdr.html");
		
		for (; i < productList->productCount; ++i) {
			printf("<tr>"
				   "<td><input type=\"radio\" name=\"spec\" value=\""
				   "%s_%s_%s_%ld\"></td>"
				   "<td>%s</td>"
				   "<td>%s</td>"
				   "<td>%s</td>"
				   "<td align=right>%ld</td>"
				   "</tr>\n",
				   products[i].manufacturer,
				   products[i].name,
				   products[i].code,
				   products[i].price,
				   products[i].manufacturer,
				   products[i].name,
				   products[i].code,
				   products[i].price);
		}
		
		printf("<input type=\"hidden\" name=\"endpoint\" value=\"%s\">\n",
			   endpoint);
		printf("<input type=\"hidden\" name=\"pubKey\" value=\"%s\">\n",
			   pubKey);
		printf("<input type=\"hidden\" name=\"privKey\" value=\"%s\">\n",
			   privKey);
		
		SendHtmlText("./ShoppingHtml/GetStockQtyFtr.html");
		SendHtmlText("./ShoppingHtml/CommonFtr.html");
    
		ReleaseProductList(productList);
	}
	else {
		/* error */
		SendHtmlText("./ShoppingHtml/CommonHdr.html");
		SendHtmlText("./ShoppingHtml/GetStockQtyErr.html");
		SendHtmlText("./ShoppingHtml/CommonFtr.html");
	}

	fprintf(stderr, "---------- MakeGetStockQtyPage end ----------\n\n");
}
bool home_kernel(void) {
    register state_t *s asm("r28") = state_ptr;

    LOG_STRING("Stepper: HOME"); LOG_U8(s->job);LOG_NEWLINE;

    if(SIM_ACTIVE)
       s->job = STEPPER_HOME_REF;

    if (s->job == STEPPER_HOME) {
        // first part of homing: find the ref switches
        // check limit switches
        #ifdef X_HOME_IS_ACTIVE
        if ((s->axis_mask & X_AXIS_MASK) && (X_HOME_IS_ACTIVE))
        #endif
            s->axis_mask &=~ X_AXIS_MASK;

        #ifdef Y_HOME_IS_ACTIVE
        if ((s->axis_mask & Y_AXIS_MASK) && (Y_HOME_IS_ACTIVE))
        #endif
            s->axis_mask &=~ Y_AXIS_MASK;

        #ifdef Z_HOME_IS_ACTIVE
        if ((s->axis_mask & Z_AXIS_MASK) && (Z_HOME_IS_ACTIVE))
        #endif
            s->axis_mask &=~ Z_AXIS_MASK;

        // step the steppers
        if (s->axis_mask & X_AXIS_MASK) {
            SET_X_STEP;
            ADVANCE_POSITION(s->position[X_AXIS], s->count_direction[X_AXIS]);
            CLR_X_STEP;
        }

        if (s->axis_mask & Y_AXIS_MASK) {
            SET_Y_STEP;
            ADVANCE_POSITION(s->position[Y_AXIS], s->count_direction[Y_AXIS]);
            CLR_Y_STEP;
        }

        if (s->axis_mask & Z_AXIS_MASK) {
            SET_Z_STEP;
            ADVANCE_POSITION(s->position[Z_AXIS], s->count_direction[Z_AXIS]);
            CLR_Z_STEP;

        }

        LOG_POS;
        if (s->axis_mask & 0x07) // not yet finished, continue in next IRQ
            return TRUE;

        // re-init for second part
        s->axis_mask = (s->axis_mask >> 4) * 0x11; // upper 4 bits stored a copy of the original mask

        s->count_direction[0] = -X_HOME_DIR;
        s->count_direction[1] = -Y_HOME_DIR;
        s->count_direction[2] = -Z_HOME_DIR;
        if (s->count_direction[X_AXIS] == 1) SET_X_INC; else SET_X_DEC;
        if (s->count_direction[Y_AXIS] == 1) SET_Y_INC; else SET_Y_DEC;
        if (s->count_direction[Z_AXIS] == 1) SET_Z_INC; else SET_Z_DEC;
        s->job = STEPPER_HOME_REF;  // search for refpoint
        OCR1A = 65535; // second part is as slow as possible
        return TRUE;

    } else {
        // 2(nd) part: find refpos

        // check limit switches
        #ifdef X_HOME_IS_ACTIVE
        if ((s->axis_mask & X_AXIS_MASK) && (!X_HOME_IS_ACTIVE))
// ALWAYS supported. may use accel/deccel for faster moves. do only use with OFF tool (or none)
bool move_kernel(void) {
    register state_t *s asm("r28") = state_ptr;
    uint8_t flag;
    uint16_t tmp;

    LOG_STRING("Stepper: MOVE\n");
    // first part: step the necessary axes
    if (s->axis_mask & X_AXIS_MASK) {
        if (s->count_direction[X_AXIS] == 1) {
            SET_X_INC;
        } else {
            SET_X_DEC;
        }
        ADVANCE_STEP_COUNTER(s->step_ctr[X_AXIS], s->steps[X_AXIS], s->steps_total, flag);
        if (flag) {
            SET_X_STEP;
            if (s->count_direction[X_AXIS] == 1) {LOG_STEP("X+");} else LOG_STEP("X-");
            ADVANCE_POSITION(s->position[X_AXIS], s->count_direction[X_AXIS]);
            CLR_X_STEP;
        }
    }
    if (s->axis_mask & Y_AXIS_MASK) {
        if (s->count_direction[Y_AXIS] == 1) {
            SET_Y_INC;
        } else {
            SET_Y_DEC;
        }
        ADVANCE_STEP_COUNTER(s->step_ctr[Y_AXIS], s->steps[Y_AXIS], s->steps_total, flag);
        if (flag) {
            SET_Y_STEP;
            if (s->count_direction[Y_AXIS] == 1) {LOG_STEP("Y+");} else LOG_STEP("Y-");
            ADVANCE_POSITION(s->position[Y_AXIS], s->count_direction[Y_AXIS]);
            CLR_Y_STEP;
        }
    }
    if (s->axis_mask & Z_AXIS_MASK) {
        if (s->count_direction[Z_AXIS] == 1) {
            SET_Z_INC;
        } else {
            SET_Z_DEC;
        }
        ADVANCE_STEP_COUNTER(s->step_ctr[Z_AXIS], s->steps[Z_AXIS], s->steps_total, flag);
        if (flag) {
            SET_Z_STEP;
            if (s->count_direction[Z_AXIS] == 1) {LOG_STEP("Z+");} else LOG_STEP("Z-");
            ADVANCE_POSITION(s->position[Z_AXIS], s->count_direction[Z_AXIS]);
            CLR_Z_STEP;
        }
    };
    LOG_POS;

    // fail-safe:
    if (!(s->axis_mask & 7))
        return FALSE; // axis mask empty -> finished

    // stupid ramp, but faster than staying at 244Hz. clamp to at most 8Khz.
    // 'mantissa' bits. the more, the slower is the accel/deccel. 6 is good
    #define MAGIC   6
    #define MAGIC2   (16-MAGIC+1)*(1<<MAGIC)
    tmp = min(s->steps_to_go, 1 + s->steps_total - s->steps_to_go);
    if (tmp <= MAGIC2)
        tmp = MAGIC2 - tmp;
    else
        tmp = 0;

    LOG_STRING("MOVE_OCR1A_CALC");LOG_X16(tmp);
    // extract exponent (as flag)
    flag = tmp >> MAGIC;LOG_U8(flag);
    if (flag) {
        // if no underflow, force highest bit set
        tmp |= 1 << MAGIC;
        flag--;
    }
    // zero exponents bits
    tmp &= (2 << MAGIC) -1;
    // solve
    for(;flag;flag--) {
        if (tmp < 32768) {
            tmp <<= 1;
        } else {
            // overflow
            tmp = 65535;
            break;
        }
    }
    LOG_X16(tmp);
    OCR1A = max(2000U, tmp);
    LOG_X16(OCR1A);LOG_STRING("ST: new OCR1A Value\n");
    return (--s->steps_to_go != 0);
}
// ONLY to be called from ISR !!!
bool arc_kernel(void) {
    register state_t *s asm("r28") = state_ptr;

    LOG_STRING("Stepper: ARC ");LOG_U8(s->job);LOG_NEWLINE;

    switch (s->job) {
    // CCW octants
    case STEPPER_ARC_CCW_OCT0:
            // octant 1: x > 0, y >= 0, x > y
            // always y+, sometimes x-
            if (s->arc_err <= s->arc_dy -s->arc_x)
                ARC_KERNEL_STEP_X_NEG;
            ARC_KERNEL_STEP_Y_POS;

            if (s->arc_y >= s->arc_x)
                s->job = STEPPER_ARC_CCW_OCT1;
            break;

    case STEPPER_ARC_CCW_OCT1:
            // octant 2: x > 0, y > 0, x <= y
            // always x-, sometimes y+
            if (s->arc_err > s->arc_y - s->arc_dx)
                ARC_KERNEL_STEP_Y_POS;
            ARC_KERNEL_STEP_X_NEG;

            if (s->arc_x <= 0)
                s->job = STEPPER_ARC_CCW_OCT2;
            break;

    case STEPPER_ARC_CCW_OCT2:
            // octant 3: x <= 0, y > 0, -x <= y
            // always x-, sometimes y-
            if (s->arc_err <= -(s->arc_dx + s->arc_y))
                ARC_KERNEL_STEP_Y_NEG;
            ARC_KERNEL_STEP_X_NEG;

            if (s->arc_x <= -s->arc_y)
                s->job = STEPPER_ARC_CCW_OCT3;
            break;

    case STEPPER_ARC_CCW_OCT3:
            // octant 4: x < 0, y > 0, -x > y
            // always y-, sometimes x-
            if (s->arc_err > -(s->arc_dy + s->arc_x))
                ARC_KERNEL_STEP_X_NEG;
            ARC_KERNEL_STEP_Y_NEG;

            if (s->arc_y <= 0)
                s->job = STEPPER_ARC_CCW_OCT4;
            break;

    case STEPPER_ARC_CCW_OCT4:
            // octant 5: x < 0, y <= 0, -x > -y
            // always y-, sometimes x+
            if (s->arc_err <= s->arc_x - s->arc_dy)
                ARC_KERNEL_STEP_X_POS;
            ARC_KERNEL_STEP_Y_NEG;

            if (s->arc_x >= s->arc_y)
                s->job = STEPPER_ARC_CCW_OCT5;
            break;

    case STEPPER_ARC_CCW_OCT5:
            // octant 6: x < 0, y < 0, -x <= -y
            // always x+, sometimes y-
            if (s->arc_err > s->arc_dx - s->arc_y)
                ARC_KERNEL_STEP_Y_NEG;
            ARC_KERNEL_STEP_X_POS;

            if (s->arc_x >= 0)
                s->job = STEPPER_ARC_CCW_OCT6;
            break;

    case STEPPER_ARC_CCW_OCT6:
            // octant 7: x >= 0, y < 0, x <= -y
            // always x+, sometimes y+
            if (s->arc_err <= s->arc_dx + s->arc_y)
                ARC_KERNEL_STEP_Y_POS;
            ARC_KERNEL_STEP_X_POS;

            if (s->arc_x >= -s->arc_y)
                s->job = STEPPER_ARC_CCW_OCT7;
            break;

    case STEPPER_ARC_CCW_OCT7:
            // octant 8: x > 0, y < 0, x > -y
            // always y+, sometimes x+
            if (s->arc_err > s->arc_x + s->arc_dy)
                ARC_KERNEL_STEP_X_POS;
            ARC_KERNEL_STEP_Y_POS;

            if (s->arc_y >= 0)
                s->job = STEPPER_ARC_CCW_OCT0;
            break;

    // CW octants
    case STEPPER_ARC_CW_OCT0:
            // octant 1: x > 0, y >= 0, x > y
            // always y-, sometimes x+
            if (s->arc_err > -s->arc_dy + s->arc_x)
                ARC_KERNEL_STEP_X_POS;
            ARC_KERNEL_STEP_Y_NEG;

            if (s->arc_y <= 0)
                s->job = STEPPER_ARC_CW_OCT7;
            break;

    case STEPPER_ARC_CW_OCT1:
            // octant 2: x > 0, y > 0, x <= y
            // always x+, sometimes y-
            if (s->arc_err <= -s->arc_y + s->arc_dx)
                ARC_KERNEL_STEP_Y_NEG;
            ARC_KERNEL_STEP_X_POS;

            if (s->arc_y < s->arc_x)
                s->job = STEPPER_ARC_CW_OCT0;
            break;

    case STEPPER_ARC_CW_OCT2:
            // octant 3: x <= 0, y > 0, -x <= y
            // always x+, sometimes y+
            if (s->arc_err > s->arc_dx + s->arc_y)
                ARC_KERNEL_STEP_Y_POS;
            ARC_KERNEL_STEP_X_POS;

            if (s->arc_x >= 0)
                s->job = STEPPER_ARC_CW_OCT1;
            break;

    case STEPPER_ARC_CW_OCT3:
            // octant 4: x < 0, y > 0, -x > y
            // always y+, sometimes x+
            if (s->arc_err <= s->arc_dy + s->arc_x)
                ARC_KERNEL_STEP_X_POS;
            ARC_KERNEL_STEP_Y_POS;

            if (s->arc_x > -s->arc_y)
                s->job = STEPPER_ARC_CW_OCT2;
            break;

    case STEPPER_ARC_CW_OCT4:
            // octant 5: x < 0, y <= 0, -x > -y
            // always y+, sometimes x-
            if (s->arc_err > -s->arc_x + s->arc_dy)
                ARC_KERNEL_STEP_X_NEG;
            ARC_KERNEL_STEP_Y_POS;

            if (s->arc_y >= 0)
                s->job = STEPPER_ARC_CW_OCT3;
            break;

    case STEPPER_ARC_CW_OCT5:
            // octant 6: x < 0, y < 0, -x <= -y
            // always x-, sometimes y+
            if (s->arc_err <= -s->arc_dx + s->arc_y)
                ARC_KERNEL_STEP_Y_POS;
            ARC_KERNEL_STEP_X_NEG;

            if (s->arc_x < s->arc_y)
                s->job = STEPPER_ARC_CW_OCT4;
            break;

    case STEPPER_ARC_CW_OCT6:
            // octant 7: x >= 0, y < 0, x <= -y
            // always x-, sometimes y-
            if (s->arc_err > -(s->arc_dx + s->arc_y))
                ARC_KERNEL_STEP_Y_NEG;
            ARC_KERNEL_STEP_X_NEG;

            if (s->arc_x <= 0)
                s->job = STEPPER_ARC_CW_OCT5;
            break;

    case STEPPER_ARC_CW_OCT7:
            // octant 8: x > 0, y < 0, x > -y
            // always y-, sometimes x-
            if (s->arc_err <= -(s->arc_x + s->arc_dy))
                ARC_KERNEL_STEP_X_NEG;
            ARC_KERNEL_STEP_Y_NEG;

            if (s->arc_x < -s->arc_y)
                s->job = STEPPER_ARC_CW_OCT6;
            break;
    };

    // handle Z movement, if any
    if (s->axis_mask & Z_AXIS_MASK) {
        uint8_t flag;
        if (s->count_direction[Z_AXIS] == 1) {
            SET_Z_INC;
        } else {
            SET_Z_DEC;
        }
        ADVANCE_STEP_COUNTER(s->step_ctr[Z_AXIS], s->steps[Z_AXIS], s->steps_total, flag);
        if (flag) {
            SET_Z_STEP;
            if (s->count_direction[Z_AXIS] == 1) {LOG_STEP("Z+");} else LOG_STEP("Z-");
            ADVANCE_POSITION(s->position[Z_AXIS], s->count_direction[Z_AXIS]);
            CLR_Z_STEP;
        }
    }

    LOG_POS;

    //~ avg_speed in x: |y|/R * mm_per_step * tickrate
    //~ total avg_speed is R/max(|x|,|y|) * mm_per_step * steprate
    //~ ->
    //~ F_CPU/OCR1A = steprate = avg_speed * max(|x|,|y|) / (R*mm_per_step)
    //~ ->
    //~ OCR1A = F_CPU * R * mm_per_step / (avg_speed * max(|x|,|y|)
    //~ at hor/vert tangents:
    //~ OCR1A_0 = F_CPU * mm_per_step / avg_speed = s-> base_ticks
    //~ ->
    //~ OCR1A = s->base_ticks * R / max(|x|,|y|)  = s->base_ticks ... sqrt(2)*s->base_ticks
    //~ -> s->base_ticks <= 40404 !!!!

    //s->speedfactor = round(256.0*sqrt(square(s->arc_x) + square(s->arc_y)) / max(abs(s->arc_x), abs(s->arc_y)));

    OCR1A = (((uint32_t) s->base_ticks) * (s->arc_radius)) / max(abs(s->arc_x),abs(s->arc_y));
    //~ OCR1A = s->base_ticks; // XXX: speedfactor correction!

    LOG_STRING("new OCR1A:");LOG_X16(OCR1A);LOG_X16(s->base_ticks);LOG_NEWLINE;

    s->steps_to_go--;
    return (s->steps_to_go != 0);
}
/******************************************************************************
 * appMain
 ******************************************************************************/
Int main(Int argc, Char *argv[])
{
    UInt32 framesize;
    Memory_AllocParams memParams = Memory_DEFAULTPARAMS;
    
    printf("******************************************************************************\n");
    printf("Sample application for testing kernels in C6Accel started.\n");
    printf("******************************************************************************\n");
    /* This call must be made before the Memory_xxx() functions as it is required for the tracing functions
     in all the codec engine APIs that are used*/
    CERuntime_init();

    /* Reset timeObj used for benchmarking*/
    Time_reset(&sTime);

    /* Create call generates a C6ACCEL handle */
    hC6 = C6accel_create(engineName, NULL,algName, NULL);

    /*Check for failure*/
    if ( hC6 == NULL)
       {printf("%s: C6accel_create() failed \n",progName);
        goto end;
    }

    /* Create buffers for use by algorithms */

    /* Want to use cached & contiguous memory to get best performance from cortex when it also uses the buffers.*/
    memParams.flags = Memory_CACHED;
    memParams.type = Memory_CONTIGHEAP;

    /* Size all buffers for 6 bytes, to cope with worst case 16 bit 422Planar*/
    framesize = (MAX_WIDTH * MAX_HEIGHT * sizeof(Int32)*3/2);

    /* Create 16bit buffers for use by algorithms*/
    pSrcBuf_16bpp = Memory_alloc(framesize, &memParams);
    if (pSrcBuf_16bpp == NULL) {
        goto end;
    }
    else {
       Memory_cacheWbInv(pSrcBuf_16bpp, framesize);
    }
    
      pOutBuf_16bpp = Memory_alloc(framesize, &memParams);
    if (pOutBuf_16bpp == NULL) {
        goto end;
    }
    else {
       Memory_cacheWbInv(pOutBuf_16bpp, framesize);
    }
    
    pRefBuf_16bpp = Memory_alloc(framesize, &memParams);
    if (pRefBuf_16bpp == NULL) {
        goto end;
    }
    else {
       Memory_cacheWbInv(pRefBuf_16bpp, framesize);
    }

      pWorkingBuf_16bpp = Memory_alloc(framesize, &memParams);
    if (pWorkingBuf_16bpp == NULL) {
        goto end;
    }
    else {
       Memory_cacheWbInv(pWorkingBuf_16bpp, framesize);
    }
    
    pWorkingBuf2_16bpp = Memory_alloc(framesize, &memParams);
    if (pWorkingBuf2_16bpp == NULL) {
        goto end;
    }
    else {
       Memory_cacheWbInv(pWorkingBuf2_16bpp, framesize);
    }
  
   #ifdef DEVICE_FLOAT
   pWorkingBuf3_16bpp = Memory_alloc(framesize, &memParams);
    if (pWorkingBuf3_16bpp == NULL) {
        goto end;
    }
    else {
       Memory_cacheWbInv(pWorkingBuf3_16bpp, framesize);
    }
    #endif
    
    /* open file for csv output*/
    OPEN_LOG_FILE("benchmarking.txt");
   
    /* Call test functions for kernels in C6accel*/
    LOG_STRING("IMGLib Functions\n");
    LOG_STRING("640x480 8bit/pixel b/w Test Image \n");
    
    printf("-----------------------------------------------------------------------------\n");
    printf("Test for Image processing functions in C6Accel: \n");
    printf("-----------------------------------------------------------------------------\n");

    c6accel_test_IMG_histogram(hC6,WIDTH,HEIGHT);
    c6accel_test_IMG_median(hC6,WIDTH,HEIGHT);
    c6accel_test_IMG_conv(hC6,WIDTH,HEIGHT);
    c6accel_test_IMG_corr(hC6,WIDTH,HEIGHT);
    c6accel_test_IMG_sobel(hC6,WIDTH,HEIGHT);
    c6accel_test_IMG_muls(hC6,WIDTH,HEIGHT);
    c6accel_test_IMG_adds(hC6,WIDTH,HEIGHT);
    c6accel_test_IMG_subs(hC6,WIDTH,HEIGHT);
    LOG_STRING("800x600 YUYV Test Image \n");
    c6accel_test_IMG_YC_demux(hC6,YUV_WIDTH,YUV_HEIGHT);
    c6accel_test_IMG_YUV422PLtoYUV422SP(hC6,2,16,16,16, 8);
    c6accel_test_IMG_YUV422SPtoYUV422ILE( hC6,2,16,16,32);
    c6accel_test_IMG_YUV422SPtoYUV420PL(hC6,2,16,16,16, 8);
    LOG_STRING("DSPLib Functions\n");
    LOG_STRING("64k sample FFT \n");
    
    printf("-----------------------------------------------------------------------------\n");
    printf("Test for Fixed point Signal processing functions in C6Accel \n");
    printf("-----------------------------------------------------------------------------\n");
    c6accel_test_DSP_FFT(hC6,N);
    c6accel_test_DSP_IFFT(hC6,N);
    c6accel_test_DSP_AUTOCOR(hC6,Nx,Nr);
    c6accel_test_DSP_DOTPROD(hC6,Nr);

    /* Implementation of this function limits
    the rows and columns of matrices to be multiples of 4 and r1 >8 */
    c6accel_test_DSP_MATMUL(hC6,ROW1,COL1,COL2,SHIFT);
    c6accel_test_DSP_FIR(hC6,NOUT,NCOEFF);
    c6accel_test_DSP_IIR(hC6,NXIN,NCOEFF);

  // No need to use these on floating point devices
  #ifndef DEVICE_FLOAT
    LOG_STRING_P1("MATH kernels tested with size of data block %d \n", NMAX+1);
    printf("-----------------------------------------------------------------------------\n");
    printf("Test for Fixed point Math functions in C6Accel\n");
    printf("-----------------------------------------------------------------------------\n");
    c6accel_test_MATH_RTSARITH(hC6,NMAX);
    c6accel_test_MATH_RTSCONV(hC6,NMAX);
    c6accel_test_MATH_IQCONV(hC6,NMAX,GLOBAL_Q, Q1);
    c6accel_test_MATH_IQMATH(hC6,NMAX,GLOBAL_Q);
    c6accel_test_MATH_IQARITH(hC6,NMAX,GLOBAL_Q);
    c6accel_test_MATH_IQTRIG(hC6,NMAX,GLOBAL_Q);
  #endif
  
  #ifdef DEVICE_FLOAT
  /*Test function calls for floating point kernels in C6accel*/ 
    printf("-----------------------------------------------------------------------------\n");
    printf("Test for Floating point Math Functions in C6Accel \n");
    printf("-----------------------------------------------------------------------------\n");
    c6accel_test_MATH_RTSARITH(hC6,NMAX);
    c6accel_test_MATH_RTSCONV(hC6,NMAX); 
    c6accel_test_MATH_RTSFLT(hC6,BUFSIZE) ;
    c6accel_test_MATH_RTSFLTDP(hC6,BUFSIZE) ;
    
    printf("-----------------------------------------------------------------------------\n");
    printf("Test for Floating point Signal processing Functions in C6accel\n");
    printf("-----------------------------------------------------------------------------\n");
    c6accel_test_DSPF_sp_fftSPxSP(hC6, Npt, rad, 0, Npt);
    c6accel_test_DSPF_VECMUL(hC6,  BUFSIZE );
    c6accel_test_DSPF_VECRECIP(hC6,  NumX );
    c6accel_test_DSPF_VECSUM_SQ(hC6,  Nelements );
    c6accel_test_DSPF_W_VEC(hC6, Mfactor,   BUFSIZE );
    c6accel_test_DSPF_DOTPRODFXNS(hC6,  Nelements);
    c6accel_test_DSPF_MATFXNS(hC6,  16,  16,  16 );
    c6accel_test_DSPF_MAT_MUL_CPLX(hC6,  4,  8,  8 ); 
    c6accel_test_DSPF_MAT_TRANS(hC6,  NumR,  NumR );
    c6accel_test_DSPF_AUTOCOR(hC6,NumX,NumR);
    c6accel_test_DSPF_CONVOL(hC6,NumH,NumR); 
    //c6accel_test_DSPF_IIR(hC6,  NumX);
    c6accel_test_DSPF_FIR(hC6, 128,  4);
    c6accel_test_DSPF_sp_ifftSPxSP(hC6, Npt, rad, 0, Npt);
    c6accel_test_DSPF_BIQUAD(hC6,  BUFSIZE);
  #endif   

    CLOSE_LOG_FILE();

end:
     // Tear down C6ACCEL
    if (hC6)
       C6accel_delete(hC6);

    if(pSrcBuf_16bpp)
        Memory_free(pSrcBuf_16bpp, framesize, &memParams);

    if(pOutBuf_16bpp)
        Memory_free(pOutBuf_16bpp, framesize, &memParams);

    if(pRefBuf_16bpp)
        Memory_free(pRefBuf_16bpp, framesize, &memParams);

    if(pWorkingBuf_16bpp)
        Memory_free(pWorkingBuf_16bpp, framesize, &memParams);

    if(pWorkingBuf2_16bpp)
        Memory_free(pWorkingBuf2_16bpp, framesize, &memParams);

    #ifdef DEVICE_FLOAT
    if(pWorkingBuf3_16bpp)
        Memory_free(pWorkingBuf3_16bpp, framesize, &memParams);
    #endif

    printf("******************************************************************************\n");
    printf("All tests done.\n");
    printf("******************************************************************************\n");
    printf("\n");

   return (0);
}
Beispiel #13
0
Font::Font(const std::string filename, size_t size) {
	// These are the characters that get stored to texture.
	// Margins around characters to prevent them from 'bleeding' into each other.
	const size_t margin = 1;
	size_t image_height = 0, image_width = 512;

	// Initialize FreeType
	FT_Library library;
	if (FT_Init_FreeType(&library)) {
		LOG_FATAL("FreeType initializing failed");
	} else {
		LOG_STRING("FreeType initialized");
	}

	// Load the font
	LOG_STRING("Loading font '" + filename + "'");

	FT_Face face;
	int error = FT_New_Face(library, filename.c_str(), 0, &face);
	if (error == FT_Err_Unknown_File_Format) {
		LOG_FATAL("Font loading failed: Unknown format of a file.");
	} else if (error) {
		LOG_FATAL("Font loading failed: The file could not be opened or read, or is broken, or else.");
	}
	LOG_STRING("Font loaded");

	// Some checks
	if (!(face->face_flags & FT_FACE_FLAG_SCALABLE)) {
		LOG_FATAL("The font is not scalable)");
	}
	if (!(face->face_flags & FT_FACE_FLAG_HORIZONTAL)) {
		LOG_FATAL("The font is not horizontal)");
	}

	// Set the font size
	FT_Set_Pixel_Sizes(face, size, 0);
	pixel_height = size;

	int max_height = 0;
	size_t x = margin, y = margin;
	// Rasterize all the characters

	int total_chars = 0;
	uint32_t gindex; // glyph index
	uint32_t unicode = FT_Get_First_Char(face, &gindex);

	while (gindex != 0) {
		char buf[100];
		FT_Get_Glyph_Name(face, gindex, buf, 100);
		//LOG_STRING("Available character: " + stringify<uint32_t>(unicode) + " (" + buf + ")");
		// Look up the character in the font file.

		if (glyphs.find(gindex) != glyphs.end()) {
			unicode2glyph[unicode] = glyphs[gindex];
			continue;
		}

		// Render the current glyph.
		FT_Load_Glyph(face, gindex, FT_LOAD_RENDER | FT_LOAD_NO_HINTING);

		// Save character metrics
		Glyph *g = glyphs[gindex] = unicode2glyph[unicode] = new Glyph; // shortcut
		g->advance = face->glyph->metrics.horiAdvance / 64;
		g->width = face->glyph->bitmap.width;
		g->height = face->glyph->bitmap.rows;
		g->bearingX = face->glyph->metrics.horiBearingX / 64;
		g->bearingY = face->glyph->metrics.horiBearingY / 64;

		// Compute kerning
		//for (int j = 0; j < 256; j++) {
		//	// Look up the second character in the font file.
		//	int char2_index = FT_Get_Char_Index(face, j);
		//	FT_Vector akerning;
		//	FT_Get_Kerning(face, char_index, char2_index, FT_KERNING_DEFAULT, &akerning);
		//	kerning[i][j] = static_cast<float>(akerning.x) / 64;
		//}

		// Save glyph bitmap
		g->data = new unsigned char[g->width * g->height];
		memcpy(g->data, face->glyph->bitmap.buffer, g->width * g->height);

		// If the line is full, go to the next line
		if (g->width + margin > image_width - x) {
			x = margin;
			y += max_height + margin;
			max_height = 0;
		}
		g->x = x;
		g->y = y;
		max_height = std::max(g->height, max_height);
		x += g->width + margin;

		total_chars += 1;
		unicode = FT_Get_Next_Char(face, unicode, &gindex);
	}
	LOG_STRING("Total chars in atlas: " + stringify<int>(total_chars));
	FT_Done_FreeType(library);

	LOG_STRING("Generating font texture atlas");
	// Compute how high the texture has to be.
	int needed_image_height = y + max_height + margin;
	// Get the first power of two in which it fits.
	image_height = 16;
	while (image_height < needed_image_height) {
		image_height *= 2;
	}

	// Allocate memory for the texture, and set it to 0.
	unsigned char *image = new unsigned char[image_height * image_width];
	for (int i = 0; i < image_height * image_width; i++) {
		image[i] = 0;
	}

	// Drawing loop
	for (std::map<uint32_t, Glyph*>::iterator gindex = glyphs.begin(); gindex != glyphs.end(); gindex++) {
		Glyph *g = gindex->second; // shortcut

		if (g->data != NULL) {
			// Fill in the texture coords
			g->tex_left = static_cast<float>(g->x) / image_width;
			g->tex_right = static_cast<float>(g->x + g->width) / image_width;
			g->tex_top = static_cast<float>(g->y) / image_height;
			g->tex_bottom = static_cast<float>(g->y + g->height) / image_height;

			// Copy the glyph bitmap to the texture atlas
			for (size_t row = 0; row < g->height; ++row) {
				memcpy(&image[g->x + (g->y + row) * image_width], &g->data[row * g->width], g->width);
			}

			delete[] g->data;
			g->data = NULL;
		}
	}
	LOG_STRING("Font texture atlas generated");

	// Create OpenGL texture from the image.
	glDeleteTextures(1, &texture);
	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA8, image_width, image_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, image);
	// Free the image memory.
	delete[] image;
	LOG_STRING("Font texture loaded");
}
bool CATDbgHelper::Open( const string& sParameter, const unsigned long iLong )
{
	LOG_FUNC_ENTRY("CATDbgHelper::Open");
	// Verify that file exits. Version 5.1.2600.5512 of dbghelp.dll does not correctly
	// return error code if missing image file. This can lead upto applicaton crash.
	if ( ! CATBase::FileExists( sParameter.c_str() ) )
	{
		LOG_STRING( "Missing image file: " << sParameter );
		return false;
	}

	// Is it urel try read map?
	if ( sParameter.find( "\\urel\\" ) != string::npos )
	{
		string sMapFile = sParameter;
		sMapFile.append( ".map" );
		ReadMapFile( sMapFile );
	}

	// Set base address used
	m_BaseAddress = iLong + AT_VIRTUAL_OFFSET_DBGHELPER;
	// Binary file (also referred as symbol).
	size_t length = sParameter.length();
	if ( length == 0 )
	{
		LOG_STRING("DbgHelp:Invalid binary parameter.");
		return false;
	}

	char* pChar = new char[ sParameter.length()+1 ];
	strcpy( pChar, sParameter.c_str() );
	// Have to be casted to PSTR before using dbg api. Even tho its typedef same.
	// This will avoid access violations bug.
	// Note pChar is not deleted because its the member pointer just casted its
	// memory allocation freed in destructor.
	if ( m_pBinaryFile )
		delete[] m_pBinaryFile;

	m_pBinaryFile = (PSTR) pChar;

	// Initialize dbghelper if not done only once.
	if ( ! CDBGHELPER_OPEN )
	{
		// Set symbol options
		SymSetOptions( SYMOPT_LOAD_LINES | SYMOPT_DEBUG | SYMOPT_UNDNAME | SYMOPT_LOAD_ANYTHING );
		if ( !SymInitialize( GetCurrentProcess(), NULL, TRUE ) )
		{
			LOG_STRING("DbgHelp:Error initializing dbghelper " << (int) GetLastError());
			return false;
		}
		LOG_STRING("DbgHelp:dbghelper opened.");
		CDBGHELPER_OPEN = true;
	}

	// Set symbol search path.
	if ( !SymSetSearchPath( GetCurrentProcess(), NULL ) )
	{
		LOG_STRING("DbgHelp:Error setting symbol search path " << (int) GetLastError());
		return false;
	}

	// Load module.
	DWORD64 ret;
	ret = SymLoadModule64( GetCurrentProcess(), NULL, m_pBinaryFile, NULL, m_BaseAddress, NULL ); // 5.1 api version.
	if ( ret != m_BaseAddress  && ret != 0)
	{
		LOG_STRING("Dbghelp:Module load failed " << (int) GetLastError());
		return false;
	}
	CDBGHELPER_CLIENTS++;
	return true;
}
bool CATDbgHelper::AddressToLine( CATMemoryAddress* result )
{
	LOG_FUNC_ENTRY("CATDbgHelper::AddressToLine");
	
	// Set state out of range
	result->SetAddressToLineState( CATMemoryAddress::OUT_OF_RANGE );

	// check that dbghelper has been initialized successfully.
	if ( ! CDBGHELPER_OPEN )
		return false;

	// Check has binary been moved, if so unload and load to new base address.
	if ( result->GetModuleStartAddress() + AT_VIRTUAL_OFFSET_DBGHELPER != m_BaseAddress )
	{
		// Unload.
		if ( SymUnloadModule64( GetCurrentProcess(), m_BaseAddress ) )
		{
			// Set new base address.
			m_BaseAddress = result->GetModuleStartAddress() + AT_VIRTUAL_OFFSET_DBGHELPER;
			// (Re)load.
			DWORD64 loading = SymLoadModule64( GetCurrentProcess(), NULL, m_pBinaryFile, NULL, m_BaseAddress, NULL );
			if ( loading != m_BaseAddress  && loading != 0)	
			{
				LOG_STRING("Dbghelp:Module load failed " << (int) GetLastError());
				return false;
			}
		}
		else
			LOG_STRING("Dbghelp:Module unload failed " << (int) GetLastError() );
	}
	// Address to find (offset+given address).
	unsigned long iAddressToFind = result->GetAddress() + AT_VIRTUAL_OFFSET_DBGHELPER;
	// Displacements of line/symbol information.
	DWORD64 displacementSymbol;
	DWORD displacementLine;
	// Structure to get symbol information.
	CSymbolInfo symbol;
	// Structure to get line information.
	CLineInfo line;
	// Find Symbol for given address 
	if( ! SymFromAddr( GetCurrentProcess(), iAddressToFind , &displacementSymbol, &symbol.si ) )
	{
		LOG_STRING("Failed to find symbol information for given line.");
		return AddressToFunction( result );
	}
	// Find line information
	if( ! SymGetLineFromAddr64( GetCurrentProcess(), iAddressToFind, &displacementLine, &line ) )
	{
		// If it fails get symbol line information
		LOG_STRING("Dbghelp:Failed to find line information for address, trying for symbol of address.");
		if( ! SymGetLineFromAddr64( GetCurrentProcess(), symbol.si.Address, &displacementLine, &line ) )
		{
			LOG_STRING("Dbghelp:Failed to find line information for symbol address.");
			return AddressToFunction( result );
		}
	}
	// Set the results.
	result->SetFileName( string( line.FileName ) );
	result->SetFunctionName( string( symbol.si.Name ) );
	result->SetExactLineNumber( (int) line.LineNumber );
	result->SetAddressToLineState( CATMemoryAddress::EXACT );
	// Return.
	return true;
}
Beispiel #16
0
int UnescapeCEscapeSequences(const char* source, char* dest,
                             vector<string> *errors) {
  GOOGLE_DCHECK(errors == NULL) << "Error reporting not implemented.";

  char* d = dest;
  const char* p = source;

  // Small optimization for case where source = dest and there's no escaping
  while ( p == d && *p != '\0' && *p != '\\' )
    p++, d++;

  while (*p != '\0') {
    if (*p != '\\') {
      *d++ = *p++;
    } else {
      switch ( *++p ) {                    // skip past the '\\'
        case '\0':
          LOG_STRING(ERROR, errors) << "String cannot end with \\";
          *d = '\0';
          return d - dest;   // we're done with p
        case 'a':  *d++ = '\a';  break;
        case 'b':  *d++ = '\b';  break;
        case 'f':  *d++ = '\f';  break;
        case 'n':  *d++ = '\n';  break;
        case 'r':  *d++ = '\r';  break;
        case 't':  *d++ = '\t';  break;
        case 'v':  *d++ = '\v';  break;
        case '\\': *d++ = '\\';  break;
        case '?':  *d++ = '\?';  break;    // \?  Who knew?
        case '\'': *d++ = '\'';  break;
        case '"':  *d++ = '\"';  break;
        case '0': case '1': case '2': case '3':  // octal digit: 1 to 3 digits
        case '4': case '5': case '6': case '7': {
          char ch = *p - '0';
          if ( IS_OCTAL_DIGIT(p[1]) )
            ch = ch * 8 + *++p - '0';
          if ( IS_OCTAL_DIGIT(p[1]) )      // safe (and easy) to do this twice
            ch = ch * 8 + *++p - '0';      // now points at last digit
          *d++ = ch;
          break;
        }
        case 'x': case 'X': {
          if (!isxdigit(p[1])) {
            if (p[1] == '\0') {
              LOG_STRING(ERROR, errors) << "String cannot end with \\x";
            } else {
              LOG_STRING(ERROR, errors) <<
                "\\x cannot be followed by non-hex digit: \\" << *p << p[1];
            }
            break;
          }
          unsigned int ch = 0;
          const char *hex_start = p;
          while (isxdigit(p[1]))  // arbitrarily many hex digits
            ch = (ch << 4) + hex_digit_to_int(*++p);
          if (ch > 0xFF)
            LOG_STRING(ERROR, errors) << "Value of " <<
              "\\" << string(hex_start, p+1-hex_start) << " exceeds 8 bits";
          *d++ = ch;
          break;
        }
#if 0  // TODO(kenton):  Support \u and \U?  Requires runetochar().
        case 'u': {
          // \uhhhh => convert 4 hex digits to UTF-8
          char32 rune = 0;
          const char *hex_start = p;
          for (int i = 0; i < 4; ++i) {
            if (isxdigit(p[1])) {  // Look one char ahead.
              rune = (rune << 4) + hex_digit_to_int(*++p);  // Advance p.
            } else {
              LOG_STRING(ERROR, errors)
                << "\\u must be followed by 4 hex digits: \\"
                <<  string(hex_start, p+1-hex_start);
              break;
            }
          }
          d += runetochar(d, &rune);
          break;
        }
        case 'U': {
          // \Uhhhhhhhh => convert 8 hex digits to UTF-8
          char32 rune = 0;
          const char *hex_start = p;
          for (int i = 0; i < 8; ++i) {
            if (isxdigit(p[1])) {  // Look one char ahead.
              // Don't change rune until we're sure this
              // is within the Unicode limit, but do advance p.
              char32 newrune = (rune << 4) + hex_digit_to_int(*++p);
              if (newrune > 0x10FFFF) {
                LOG_STRING(ERROR, errors)
                  << "Value of \\"
                  << string(hex_start, p + 1 - hex_start)
                  << " exceeds Unicode limit (0x10FFFF)";
                break;
              } else {
                rune = newrune;
              }
            } else {
              LOG_STRING(ERROR, errors)
                << "\\U must be followed by 8 hex digits: \\"
                <<  string(hex_start, p+1-hex_start);
              break;
            }
          }
          d += runetochar(d, &rune);
          break;
        }
#endif
        default:
          LOG_STRING(ERROR, errors) << "Unknown escape sequence: \\" << *p;
      }
      p++;                                 // read past letter we escaped
    }
  }
  *d = '\0';
  return d - dest;
}