Blame pttc/src/parse.c

Packit b1f7ae
/*
Packit b1f7ae
 * Copyright (c) 2013-2017, Intel Corporation
Packit b1f7ae
 *
Packit b1f7ae
 * Redistribution and use in source and binary forms, with or without
Packit b1f7ae
 * modification, are permitted provided that the following conditions are met:
Packit b1f7ae
 *
Packit b1f7ae
 *  * Redistributions of source code must retain the above copyright notice,
Packit b1f7ae
 *    this list of conditions and the following disclaimer.
Packit b1f7ae
 *  * Redistributions in binary form must reproduce the above copyright notice,
Packit b1f7ae
 *    this list of conditions and the following disclaimer in the documentation
Packit b1f7ae
 *    and/or other materials provided with the distribution.
Packit b1f7ae
 *  * Neither the name of Intel Corporation nor the names of its contributors
Packit b1f7ae
 *    may be used to endorse or promote products derived from this software
Packit b1f7ae
 *    without specific prior written permission.
Packit b1f7ae
 *
Packit b1f7ae
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Packit b1f7ae
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit b1f7ae
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit b1f7ae
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
Packit b1f7ae
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
Packit b1f7ae
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
Packit b1f7ae
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
Packit b1f7ae
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
Packit b1f7ae
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
Packit b1f7ae
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
Packit b1f7ae
 * POSSIBILITY OF SUCH DAMAGE.
Packit b1f7ae
 */
Packit b1f7ae
Packit b1f7ae
#include "errcode.h"
Packit b1f7ae
#include "parse.h"
Packit b1f7ae
#include "util.h"
Packit b1f7ae
Packit b1f7ae
#include <ctype.h>
Packit b1f7ae
#include <stdio.h>
Packit b1f7ae
#include <stdlib.h>
Packit b1f7ae
#include <string.h>
Packit b1f7ae
Packit b1f7ae
const char *pt_suffix = ".pt";
Packit b1f7ae
const char *exp_suffix = ".exp";
Packit b1f7ae
Packit b1f7ae
enum {
Packit b1f7ae
	pd_len = 1024
Packit b1f7ae
};
Packit b1f7ae
Packit b1f7ae
/* Deallocates the memory used by @p, closes all files, clears and
Packit b1f7ae
 * zeroes the fields.
Packit b1f7ae
 */
Packit b1f7ae
static void p_free(struct parser *p)
Packit b1f7ae
{
Packit b1f7ae
	if (!p)
Packit b1f7ae
		return;
Packit b1f7ae
Packit b1f7ae
	yasm_free(p->y);
Packit b1f7ae
	pd_free(p->pd);
Packit b1f7ae
	l_free(p->pt_labels);
Packit b1f7ae
	free(p->ptfilename);
Packit b1f7ae
Packit b1f7ae
	free(p);
Packit b1f7ae
}
Packit b1f7ae
Packit b1f7ae
/* Initializes @p with @pttfile and @conf.
Packit b1f7ae
 *
Packit b1f7ae
 * Returns 0 on success; a negative enum errcode otherwise.
Packit b1f7ae
 * Returns -err_internal if @p is the NULL pointer.
Packit b1f7ae
 */
Packit b1f7ae
static struct parser *p_alloc(const char *pttfile, const struct pt_config *conf)
Packit b1f7ae
{
Packit b1f7ae
	size_t n;
Packit b1f7ae
	struct parser *p;
Packit b1f7ae
Packit b1f7ae
	if (!conf)
Packit b1f7ae
		return NULL;
Packit b1f7ae
Packit b1f7ae
	if (!pttfile)
Packit b1f7ae
		return NULL;
Packit b1f7ae
Packit b1f7ae
	p = calloc(1, sizeof(*p));
Packit b1f7ae
	if (!p)
Packit b1f7ae
		return NULL;
Packit b1f7ae
Packit b1f7ae
	p->y = yasm_alloc(pttfile);
Packit b1f7ae
	if (!p->y)
Packit b1f7ae
		goto error;
Packit b1f7ae
Packit b1f7ae
	n = strlen(p->y->fileroot) + 1;
Packit b1f7ae
Packit b1f7ae
	p->ptfilename = malloc(n+strlen(pt_suffix));
Packit b1f7ae
	if (!p->ptfilename)
Packit b1f7ae
		goto error;
Packit b1f7ae
Packit b1f7ae
	strcpy(p->ptfilename, p->y->fileroot);
Packit b1f7ae
	strcat(p->ptfilename, pt_suffix);
Packit b1f7ae
Packit b1f7ae
	p->pd = pd_alloc(pd_len);
Packit b1f7ae
	if (!p->pd)
Packit b1f7ae
		goto error;
Packit b1f7ae
Packit b1f7ae
	p->pt_labels = l_alloc();
Packit b1f7ae
	if (!p->pt_labels)
Packit b1f7ae
		goto error;
Packit b1f7ae
Packit b1f7ae
	p->conf = conf;
Packit b1f7ae
Packit b1f7ae
	return p;
Packit b1f7ae
Packit b1f7ae
error:
Packit b1f7ae
	p_free(p);
Packit b1f7ae
	return NULL;
Packit b1f7ae
}
Packit b1f7ae
Packit b1f7ae
/* Generates an .exp filename following the scheme:
Packit b1f7ae
 *	<fileroot>[-<extra>].exp
Packit b1f7ae
 */
Packit b1f7ae
static char *expfilename(struct parser *p, const char *extra)
Packit b1f7ae
{
Packit b1f7ae
	char *filename;
Packit b1f7ae
	/* reserve enough space to hold the string
Packit b1f7ae
	 *   "-cpu_fffff_mmm_sss" + 1 for the trailing null character.
Packit b1f7ae
	 */
Packit b1f7ae
	char cpu_suffix[19];
Packit b1f7ae
	size_t n;
Packit b1f7ae
Packit b1f7ae
	if (!extra)
Packit b1f7ae
		extra = "";
Packit b1f7ae
	*cpu_suffix = '\0';
Packit b1f7ae
Packit b1f7ae
	/* determine length of resulting filename, which looks like:
Packit b1f7ae
	 *   <fileroot>[-<extra>][-cpu_<f>_<m>_<s>].exp
Packit b1f7ae
	 */
Packit b1f7ae
	n = strlen(p->y->fileroot);
Packit b1f7ae
Packit b1f7ae
	if (*extra != '\0')
Packit b1f7ae
		/* the extra string is prepended with a -.  */
Packit b1f7ae
		n += 1 + strlen(extra);
Packit b1f7ae
Packit b1f7ae
	if (p->conf->cpu.vendor != pcv_unknown) {
Packit b1f7ae
		struct pt_cpu cpu;
Packit b1f7ae
Packit b1f7ae
		cpu = p->conf->cpu;
Packit b1f7ae
		if (cpu.stepping)
Packit b1f7ae
			n += sprintf(cpu_suffix,
Packit b1f7ae
				     "-cpu_%" PRIu16 "_%" PRIu8 "_%" PRIu8 "",
Packit b1f7ae
				     cpu.family, cpu.model, cpu.stepping);
Packit b1f7ae
		else
Packit b1f7ae
			n += sprintf(cpu_suffix,
Packit b1f7ae
				     "-cpu_%" PRIu16 "_%" PRIu8 "", cpu.family,
Packit b1f7ae
				     cpu.model);
Packit b1f7ae
	}
Packit b1f7ae
Packit b1f7ae
	n += strlen(exp_suffix);
Packit b1f7ae
Packit b1f7ae
	/* trailing null character.  */
Packit b1f7ae
	n += 1;
Packit b1f7ae
Packit b1f7ae
	filename = malloc(n);
Packit b1f7ae
	if (!filename)
Packit b1f7ae
		return NULL;
Packit b1f7ae
Packit b1f7ae
	strcpy(filename, p->y->fileroot);
Packit b1f7ae
	if (*extra != '\0') {
Packit b1f7ae
		strcat(filename, "-");
Packit b1f7ae
		strcat(filename, extra);
Packit b1f7ae
	}
Packit b1f7ae
	strcat(filename, cpu_suffix);
Packit b1f7ae
	strcat(filename, exp_suffix);
Packit b1f7ae
Packit b1f7ae
	return filename;
Packit b1f7ae
}
Packit b1f7ae
Packit b1f7ae
/* Returns true if @c is part of a label; false otherwise.  */
Packit b1f7ae
static int islabelchar(int c)
Packit b1f7ae
{
Packit b1f7ae
	if (isalnum(c))
Packit b1f7ae
		return 1;
Packit b1f7ae
Packit b1f7ae
	switch (c) {
Packit b1f7ae
	case '_':
Packit b1f7ae
		return 1;
Packit b1f7ae
	}
Packit b1f7ae
Packit b1f7ae
	return 0;
Packit b1f7ae
}
Packit b1f7ae
Packit b1f7ae
/* Generates the content of the .exp file by printing all lines with
Packit b1f7ae
 * everything up to and including the first comment semicolon removed.
Packit b1f7ae
 *
Packit b1f7ae
 * Returns 0 on success; a negative enum errcode otherwise.
Packit b1f7ae
 * Returns -err_internal if @p is the NULL pointer.
Packit b1f7ae
 * Returns -err_file_write if the .exp file could not be fully written.
Packit b1f7ae
 */
Packit b1f7ae
static int p_gen_expfile(struct parser *p)
Packit b1f7ae
{
Packit b1f7ae
	int errcode;
Packit b1f7ae
	enum { slen = 1024 };
Packit b1f7ae
	char s[slen];
Packit b1f7ae
	struct pt_directive *pd;
Packit b1f7ae
	char *filename;
Packit b1f7ae
	FILE *f;
Packit b1f7ae
Packit b1f7ae
	if (bug_on(!p))
Packit b1f7ae
		return -err_internal;
Packit b1f7ae
Packit b1f7ae
	pd = p->pd;
Packit b1f7ae
Packit b1f7ae
	/* the directive in the current line must be the .exp directive.  */
Packit b1f7ae
	errcode = yasm_pd_parse(p->y, pd);
Packit b1f7ae
	if (bug_on(errcode < 0))
Packit b1f7ae
		return -err_internal;
Packit b1f7ae
Packit b1f7ae
	if (bug_on(strcmp(pd->name, ".exp") != 0))
Packit b1f7ae
		return -err_internal;
Packit b1f7ae
Packit b1f7ae
	filename = expfilename(p, pd->payload);
Packit b1f7ae
	if (!filename)
Packit b1f7ae
		return -err_no_mem;
Packit b1f7ae
	f = fopen(filename, "w");
Packit b1f7ae
	if (!f) {
Packit b1f7ae
		free(filename);
Packit b1f7ae
		return -err_file_open;
Packit b1f7ae
	}
Packit b1f7ae
Packit b1f7ae
	for (;;) {
Packit b1f7ae
		int i;
Packit b1f7ae
		char *line, *comment;
Packit b1f7ae
Packit b1f7ae
		errcode = yasm_next_line(p->y, s, slen);
Packit b1f7ae
		if (errcode < 0)
Packit b1f7ae
			break;
Packit b1f7ae
Packit b1f7ae
		errcode = yasm_pd_parse(p->y, pd);
Packit b1f7ae
		if (errcode < 0 && errcode != -err_no_directive)
Packit b1f7ae
			break;
Packit b1f7ae
Packit b1f7ae
		if (errcode == 0 && strcmp(pd->name, ".exp") == 0) {
Packit b1f7ae
			fclose(f);
Packit b1f7ae
			printf("%s\n", filename);
Packit b1f7ae
			free(filename);
Packit b1f7ae
			filename = expfilename(p, pd->payload);
Packit b1f7ae
			if (!filename)
Packit b1f7ae
				return -err_no_mem;
Packit b1f7ae
			f = fopen(filename, "w");
Packit b1f7ae
			if (!f) {
Packit b1f7ae
				free(filename);
Packit b1f7ae
				return -err_file_open;
Packit b1f7ae
			}
Packit b1f7ae
			continue;
Packit b1f7ae
		}
Packit b1f7ae
Packit b1f7ae
		line = strchr(s, ';');
Packit b1f7ae
		if (!line)
Packit b1f7ae
			continue;
Packit b1f7ae
Packit b1f7ae
		line += 1;
Packit b1f7ae
Packit b1f7ae
		comment = strchr(line, '#');
Packit b1f7ae
		if (comment)
Packit b1f7ae
			*comment = '\0';
Packit b1f7ae
Packit b1f7ae
		/* remove trailing spaces.  */
Packit b1f7ae
		for (i = (int) strlen(line)-1; i >= 0 && isspace(line[i]); i--)
Packit b1f7ae
			line[i] = '\0';
Packit b1f7ae
Packit b1f7ae
		for (;;) {
Packit b1f7ae
			char *tmp, label[256];
Packit b1f7ae
			uint64_t addr;
Packit b1f7ae
			int zero_padding, qmark_padding, qmark_size, status;
Packit b1f7ae
Packit b1f7ae
			zero_padding = 0;
Packit b1f7ae
			qmark_padding = 0;
Packit b1f7ae
			qmark_size = 0;
Packit b1f7ae
			status = 0;
Packit b1f7ae
Packit b1f7ae
			/* find the label character in the string.
Packit b1f7ae
			 * if there is no label character, we just print
Packit b1f7ae
			 * the rest of the line and end.
Packit b1f7ae
			 */
Packit b1f7ae
			tmp = strchr(line, '%');
Packit b1f7ae
			if (!tmp) {
Packit b1f7ae
				if (fprintf(f, "%s", line) < 0) {
Packit b1f7ae
					errcode = -err_file_write;
Packit b1f7ae
					goto error;
Packit b1f7ae
				}
Packit b1f7ae
				break;
Packit b1f7ae
			}
Packit b1f7ae
Packit b1f7ae
			/* make the label character a null byte and
Packit b1f7ae
			 * print the first portion, which does not
Packit b1f7ae
			 * belong to the label into the file.
Packit b1f7ae
			 */
Packit b1f7ae
			*tmp = '\0';
Packit b1f7ae
			if (fprintf(f, "%s", line) < 0) {
Packit b1f7ae
				errcode = -err_file_write;
Packit b1f7ae
				goto error;
Packit b1f7ae
			}
Packit b1f7ae
Packit b1f7ae
			/* test if there is a valid label name after the %.  */
Packit b1f7ae
			line = tmp+1;
Packit b1f7ae
			if (*line == '\0' || isspace(*line)) {
Packit b1f7ae
				errcode = -err_no_label;
Packit b1f7ae
				goto error;
Packit b1f7ae
			}
Packit b1f7ae
Packit b1f7ae
			/* check if zero padding is requested.  */
Packit b1f7ae
			if (*line == '0') {
Packit b1f7ae
				zero_padding = 1;
Packit b1f7ae
				line += 1;
Packit b1f7ae
			}
Packit b1f7ae
			/* chek if ? padding is requested.  */
Packit b1f7ae
			else if (*line == '?') {
Packit b1f7ae
				qmark_padding = 1;
Packit b1f7ae
				zero_padding = 1;
Packit b1f7ae
				qmark_size = 0;
Packit b1f7ae
				line += 1;
Packit b1f7ae
			}
Packit b1f7ae
Packit b1f7ae
			/* advance i to the first non alpha-numeric
Packit b1f7ae
			 * character. all characters everything from
Packit b1f7ae
			 * line[0] to line[i-1] belongs to the label
Packit b1f7ae
			 * name.
Packit b1f7ae
			 */
Packit b1f7ae
			for (i = 0; islabelchar(line[i]); i++)
Packit b1f7ae
				;
Packit b1f7ae
Packit b1f7ae
			if (i > 255) {
Packit b1f7ae
				errcode = -err_label_name;
Packit b1f7ae
				goto error;
Packit b1f7ae
			}
Packit b1f7ae
			strncpy(label, line, i);
Packit b1f7ae
			label[i] = '\0';
Packit b1f7ae
Packit b1f7ae
			/* advance to next character.  */
Packit b1f7ae
			line = &line[i];
Packit b1f7ae
Packit b1f7ae
			/* lookup the label name and print it to the
Packit b1f7ae
			 * output file.
Packit b1f7ae
			 */
Packit b1f7ae
			errcode = yasm_lookup_label(p->y, &addr, label);
Packit b1f7ae
			if (errcode < 0) {
Packit b1f7ae
				errcode = l_lookup(p->pt_labels, &addr, label);
Packit b1f7ae
				if (errcode < 0)
Packit b1f7ae
					goto error;
Packit b1f7ae
Packit b1f7ae
				if (zero_padding)
Packit b1f7ae
					status = fprintf(f, "%016" PRIx64, addr);
Packit b1f7ae
				else
Packit b1f7ae
					status = fprintf(f, "%" PRIx64, addr);
Packit b1f7ae
Packit b1f7ae
				if (status < 0) {
Packit b1f7ae
					errcode = -err_file_write;
Packit b1f7ae
					goto error;
Packit b1f7ae
				}
Packit b1f7ae
Packit b1f7ae
				continue;
Packit b1f7ae
			}
Packit b1f7ae
Packit b1f7ae
			/* check if masking is requested.  */
Packit b1f7ae
			if (*line == '.') {
Packit b1f7ae
				char *endptr;
Packit b1f7ae
				long int n;
Packit b1f7ae
Packit b1f7ae
				line += 1;
Packit b1f7ae
Packit b1f7ae
				n = strtol(line, &endptr, 0);
Packit b1f7ae
				/* check if strtol made progress and
Packit b1f7ae
				 * stops on a space or null byte.
Packit b1f7ae
				 * otherwise the int could not be
Packit b1f7ae
				 * parsed.
Packit b1f7ae
				 */
Packit b1f7ae
				if (line == endptr ||
Packit b1f7ae
				    (*endptr != '\0' && !isspace(*endptr)
Packit b1f7ae
				     && !ispunct(*endptr))) {
Packit b1f7ae
					errcode = -err_parse_int;
Packit b1f7ae
					goto error;
Packit b1f7ae
				}
Packit b1f7ae
				addr &= (1ull << (n << 3)) - 1ull;
Packit b1f7ae
				line = endptr;
Packit b1f7ae
Packit b1f7ae
				qmark_size = 8 - n;
Packit b1f7ae
			}
Packit b1f7ae
Packit b1f7ae
			if (qmark_padding) {
Packit b1f7ae
				for (i = 0; i < qmark_size; ++i) {
Packit b1f7ae
					status = fprintf(f, "??");
Packit b1f7ae
					if (status < 0) {
Packit b1f7ae
						errcode = -err_file_write;
Packit b1f7ae
						goto error;
Packit b1f7ae
					}
Packit b1f7ae
				}
Packit b1f7ae
Packit b1f7ae
				for (; i < 8; ++i) {
Packit b1f7ae
					uint8_t byte;
Packit b1f7ae
Packit b1f7ae
					byte = (uint8_t)(addr >> ((7 - i) * 8));
Packit b1f7ae
Packit b1f7ae
					status = fprintf(f, "%02" PRIx8, byte);
Packit b1f7ae
					if (status < 0) {
Packit b1f7ae
						errcode = -err_file_write;
Packit b1f7ae
						goto error;
Packit b1f7ae
					}
Packit b1f7ae
				}
Packit b1f7ae
			} else if (zero_padding)
Packit b1f7ae
				status = fprintf(f, "%016" PRIx64, addr);
Packit b1f7ae
			else
Packit b1f7ae
				status = fprintf(f, "%" PRIx64, addr);
Packit b1f7ae
Packit b1f7ae
			if (status < 0) {
Packit b1f7ae
				errcode = -err_file_write;
Packit b1f7ae
				goto error;
Packit b1f7ae
			}
Packit b1f7ae
Packit b1f7ae
		}
Packit b1f7ae
Packit b1f7ae
		if (fprintf(f, "\n") < 0) {
Packit b1f7ae
			errcode = -err_file_write;
Packit b1f7ae
			goto error;
Packit b1f7ae
		}
Packit b1f7ae
	}
Packit b1f7ae
Packit b1f7ae
error:
Packit b1f7ae
Packit b1f7ae
	fclose(f);
Packit b1f7ae
	if (errcode < 0 && errcode != -err_out_of_range) {
Packit b1f7ae
		fprintf(stderr, "fatal: %s could not be created:\n", filename);
Packit b1f7ae
		yasm_print_err(p->y, "", errcode);
Packit b1f7ae
		remove(filename);
Packit b1f7ae
	} else
Packit b1f7ae
		printf("%s\n", filename);
Packit b1f7ae
	free(filename);
Packit b1f7ae
Packit b1f7ae
	/* If there are no lines left, we are done.  */
Packit b1f7ae
	if (errcode == -err_out_of_range)
Packit b1f7ae
		return 0;
Packit b1f7ae
Packit b1f7ae
	return errcode;
Packit b1f7ae
}
Packit b1f7ae
Packit b1f7ae
static void p_close_files(struct parser *p)
Packit b1f7ae
{
Packit b1f7ae
	if (p->ptfile) {
Packit b1f7ae
		fclose(p->ptfile);
Packit b1f7ae
		p->ptfile = NULL;
Packit b1f7ae
	}
Packit b1f7ae
}
Packit b1f7ae
Packit b1f7ae
static int p_open_files(struct parser *p)
Packit b1f7ae
{
Packit b1f7ae
	p->ptfile = fopen(p->ptfilename, "wb");
Packit b1f7ae
	if (!p->ptfile) {
Packit b1f7ae
		fprintf(stderr, "open %s failed\n", p->ptfilename);
Packit b1f7ae
		goto error;
Packit b1f7ae
	}
Packit b1f7ae
	return 0;
Packit b1f7ae
Packit b1f7ae
error:
Packit b1f7ae
	p_close_files(p);
Packit b1f7ae
	return -err_file_open;
Packit b1f7ae
}
Packit b1f7ae
Packit b1f7ae
/* Processes the current directive.
Packit b1f7ae
 * If the encoder returns an error, a message including current file and
Packit b1f7ae
 * line number together with the pt error string is printed on stderr.
Packit b1f7ae
 *
Packit b1f7ae
 * Returns 0 on success; a negative enum errcode otherwise.
Packit b1f7ae
 * Returns -err_internal if @p or @e is the NULL pointer.
Packit b1f7ae
 * Returns -err_parse_missing_directive if there was a pt directive marker,
Packit b1f7ae
 * but no directive.
Packit b1f7ae
 * Returns -stop_process if the .exp directive was encountered.
Packit b1f7ae
 * Returns -err_pt_lib if the pt encoder returned an error.
Packit b1f7ae
 * Returns -err_parse if a general parsing error was encountered.
Packit b1f7ae
 * Returns -err_parse_unknown_directive if there was an unknown pt directive.
Packit b1f7ae
 */
Packit b1f7ae
static int p_process(struct parser *p, struct pt_encoder *e)
Packit b1f7ae
{
Packit b1f7ae
	int bytes_written;
Packit b1f7ae
	int errcode;
Packit b1f7ae
	char *directive, *payload, *pt_label_name, *tmp;
Packit b1f7ae
	struct pt_directive *pd;
Packit b1f7ae
	struct pt_packet packet;
Packit b1f7ae
Packit b1f7ae
	if (bug_on(!p))
Packit b1f7ae
		return -err_internal;
Packit b1f7ae
Packit b1f7ae
	if (bug_on(!e))
Packit b1f7ae
		return -err_internal;
Packit b1f7ae
Packit b1f7ae
	pd = p->pd;
Packit b1f7ae
	if (!pd)
Packit b1f7ae
		return -err_internal;
Packit b1f7ae
Packit b1f7ae
	directive = pd->name;
Packit b1f7ae
	payload = pd->payload;
Packit b1f7ae
Packit b1f7ae
	pt_label_name = NULL;
Packit b1f7ae
	bytes_written = 0;
Packit b1f7ae
	errcode = 0;
Packit b1f7ae
Packit b1f7ae
	/* find a label name.  */
Packit b1f7ae
	tmp = strchr(directive, ':');
Packit b1f7ae
	if (tmp) {
Packit b1f7ae
		uint64_t x;
Packit b1f7ae
Packit b1f7ae
		pt_label_name = directive;
Packit b1f7ae
		directive = tmp+1;
Packit b1f7ae
		*tmp = '\0';
Packit b1f7ae
Packit b1f7ae
		/* ignore whitespace between label and directive. */
Packit b1f7ae
		while (isspace(*directive))
Packit b1f7ae
			directive += 1;
Packit b1f7ae
Packit b1f7ae
		/* if we can lookup a yasm label with the same name, the
Packit b1f7ae
		 * current pt directive label is invalid.  */
Packit b1f7ae
		errcode = yasm_lookup_label(p->y, &x, pt_label_name);
Packit b1f7ae
		if (errcode == 0)
Packit b1f7ae
			errcode = -err_label_not_unique;
Packit b1f7ae
Packit b1f7ae
		if (errcode != -err_no_label)
Packit b1f7ae
			return yasm_print_err(p->y, "label lookup",
Packit b1f7ae
					      errcode);
Packit b1f7ae
Packit b1f7ae
		/* if we can lookup a pt directive label with the same
Packit b1f7ae
		 * name, the current pt directive label is invalid.  */
Packit b1f7ae
		errcode = l_lookup(p->pt_labels, &x, pt_label_name);
Packit b1f7ae
		if (errcode == 0)
Packit b1f7ae
			errcode = -err_label_not_unique;
Packit b1f7ae
Packit b1f7ae
		if (errcode != -err_no_label)
Packit b1f7ae
			return yasm_print_err(p->y, "label lookup",
Packit b1f7ae
					      -err_label_not_unique);
Packit b1f7ae
	}
Packit b1f7ae
Packit b1f7ae
	/* now try to match the directive string and call the
Packit b1f7ae
	 * corresponding function that parses the payload and emits an
Packit b1f7ae
	 * according packet.
Packit b1f7ae
	 */
Packit b1f7ae
	if (strcmp(directive, "") == 0)
Packit b1f7ae
		return yasm_print_err(p->y, "invalid syntax",
Packit b1f7ae
				      -err_parse_missing_directive);
Packit b1f7ae
	else if (strcmp(directive, ".exp") == 0) {
Packit b1f7ae
		/* this is the end of processing pt directives, so we
Packit b1f7ae
		 * add a p_last label to the pt directive labels.
Packit b1f7ae
		 */
Packit b1f7ae
		errcode = l_append(p->pt_labels, "eos", p->pt_bytes_written);
Packit b1f7ae
		if (errcode < 0)
Packit b1f7ae
			return yasm_print_err(p->y, "append label", errcode);
Packit b1f7ae
Packit b1f7ae
		return -stop_process;
Packit b1f7ae
	}
Packit b1f7ae
Packit b1f7ae
	if (strcmp(directive, "psb") == 0) {
Packit b1f7ae
		errcode = parse_empty(payload);
Packit b1f7ae
		if (errcode < 0) {
Packit b1f7ae
			yasm_print_err(p->y, "psb: parsing failed", errcode);
Packit b1f7ae
			goto error;
Packit b1f7ae
		}
Packit b1f7ae
		packet.type = ppt_psb;
Packit b1f7ae
	} else if (strcmp(directive, "psbend") == 0) {
Packit b1f7ae
		errcode = parse_empty(payload);
Packit b1f7ae
		if (errcode < 0) {
Packit b1f7ae
			yasm_print_err(p->y, "psbend: parsing failed", errcode);
Packit b1f7ae
			goto error;
Packit b1f7ae
		}
Packit b1f7ae
		packet.type = ppt_psbend;
Packit b1f7ae
	} else if (strcmp(directive, "pad") == 0) {
Packit b1f7ae
		errcode = parse_empty(payload);
Packit b1f7ae
		if (errcode < 0) {
Packit b1f7ae
			yasm_print_err(p->y, "pad: parsing failed", errcode);
Packit b1f7ae
			goto error;
Packit b1f7ae
		}
Packit b1f7ae
		packet.type = ppt_pad;
Packit b1f7ae
	} else if (strcmp(directive, "ovf") == 0) {
Packit b1f7ae
		errcode = parse_empty(payload);
Packit b1f7ae
		if (errcode < 0) {
Packit b1f7ae
			yasm_print_err(p->y, "ovf: parsing failed", errcode);
Packit b1f7ae
			goto error;
Packit b1f7ae
		}
Packit b1f7ae
		packet.type = ppt_ovf;
Packit b1f7ae
	} else if (strcmp(directive, "stop") == 0) {
Packit b1f7ae
		errcode = parse_empty(payload);
Packit b1f7ae
		if (errcode < 0) {
Packit b1f7ae
			yasm_print_err(p->y, "stop: parsing failed", errcode);
Packit b1f7ae
			goto error;
Packit b1f7ae
		}
Packit b1f7ae
		packet.type = ppt_stop;
Packit b1f7ae
	} else if (strcmp(directive, "tnt") == 0) {
Packit b1f7ae
		errcode = parse_tnt(&packet.payload.tnt.payload,
Packit b1f7ae
				    &packet.payload.tnt.bit_size, payload);
Packit b1f7ae
		if (errcode < 0) {
Packit b1f7ae
			yasm_print_err(p->y, "tnt: parsing failed", errcode);
Packit b1f7ae
			goto error;
Packit b1f7ae
		}
Packit b1f7ae
		packet.type = ppt_tnt_8;
Packit b1f7ae
	} else if (strcmp(directive, "tnt64") == 0) {
Packit b1f7ae
		errcode = parse_tnt(&packet.payload.tnt.payload,
Packit b1f7ae
				    &packet.payload.tnt.bit_size, payload);
Packit b1f7ae
		if (errcode < 0) {
Packit b1f7ae
			yasm_print_err(p->y, "tnt64: parsing failed", errcode);
Packit b1f7ae
			goto error;
Packit b1f7ae
		}
Packit b1f7ae
		packet.type = ppt_tnt_64;
Packit b1f7ae
	} else if (strcmp(directive, "tip") == 0) {
Packit b1f7ae
		errcode = parse_ip(p, &packet.payload.ip.ip,
Packit b1f7ae
				   &packet.payload.ip.ipc, payload);
Packit b1f7ae
		if (errcode < 0) {
Packit b1f7ae
			yasm_print_err(p->y, "tip: parsing failed", errcode);
Packit b1f7ae
			goto error;
Packit b1f7ae
		}
Packit b1f7ae
		packet.type = ppt_tip;
Packit b1f7ae
	} else if (strcmp(directive, "tip.pge") == 0) {
Packit b1f7ae
		errcode = parse_ip(p, &packet.payload.ip.ip,
Packit b1f7ae
				   &packet.payload.ip.ipc, payload);
Packit b1f7ae
		if (errcode < 0) {
Packit b1f7ae
			yasm_print_err(p->y, "tip.pge: parsing failed",
Packit b1f7ae
				       errcode);
Packit b1f7ae
			goto error;
Packit b1f7ae
		}
Packit b1f7ae
		packet.type = ppt_tip_pge;
Packit b1f7ae
	} else if (strcmp(directive, "tip.pgd") == 0) {
Packit b1f7ae
		errcode = parse_ip(p, &packet.payload.ip.ip,
Packit b1f7ae
				   &packet.payload.ip.ipc, payload);
Packit b1f7ae
		if (errcode < 0) {
Packit b1f7ae
			yasm_print_err(p->y, "tip.pgd: parsing failed",
Packit b1f7ae
				       errcode);
Packit b1f7ae
			goto error;
Packit b1f7ae
		}
Packit b1f7ae
		packet.type = ppt_tip_pgd;
Packit b1f7ae
	} else if (strcmp(directive, "fup") == 0) {
Packit b1f7ae
		errcode = parse_ip(p, &packet.payload.ip.ip,
Packit b1f7ae
				   &packet.payload.ip.ipc, payload);
Packit b1f7ae
		if (errcode < 0) {
Packit b1f7ae
			yasm_print_err(p->y, "fup: parsing failed", errcode);
Packit b1f7ae
			goto error;
Packit b1f7ae
		}
Packit b1f7ae
		packet.type = ppt_fup;
Packit b1f7ae
	} else if (strcmp(directive, "mode.exec") == 0) {
Packit b1f7ae
		if (strcmp(payload, "16bit") == 0) {
Packit b1f7ae
			packet.payload.mode.bits.exec.csl = 0;
Packit b1f7ae
			packet.payload.mode.bits.exec.csd = 0;
Packit b1f7ae
		} else if (strcmp(payload, "64bit") == 0) {
Packit b1f7ae
			packet.payload.mode.bits.exec.csl = 1;
Packit b1f7ae
			packet.payload.mode.bits.exec.csd = 0;
Packit b1f7ae
		} else if (strcmp(payload, "32bit") == 0) {
Packit b1f7ae
			packet.payload.mode.bits.exec.csl = 0;
Packit b1f7ae
			packet.payload.mode.bits.exec.csd = 1;
Packit b1f7ae
		} else {
Packit b1f7ae
			errcode = yasm_print_err(p->y,
Packit b1f7ae
						 "mode.exec: argument must be one of \"16bit\", \"64bit\" or \"32bit\"",
Packit b1f7ae
						 -err_parse);
Packit b1f7ae
			goto error;
Packit b1f7ae
		}
Packit b1f7ae
		packet.payload.mode.leaf = pt_mol_exec;
Packit b1f7ae
		packet.type = ppt_mode;
Packit b1f7ae
	} else if (strcmp(directive, "mode.tsx") == 0) {
Packit b1f7ae
		if (strcmp(payload, "begin") == 0) {
Packit b1f7ae
			packet.payload.mode.bits.tsx.intx = 1;
Packit b1f7ae
			packet.payload.mode.bits.tsx.abrt = 0;
Packit b1f7ae
		} else if (strcmp(payload, "abort") == 0) {
Packit b1f7ae
			packet.payload.mode.bits.tsx.intx = 0;
Packit b1f7ae
			packet.payload.mode.bits.tsx.abrt = 1;
Packit b1f7ae
		} else if (strcmp(payload, "commit") == 0) {
Packit b1f7ae
			packet.payload.mode.bits.tsx.intx = 0;
Packit b1f7ae
			packet.payload.mode.bits.tsx.abrt = 0;
Packit b1f7ae
		} else {
Packit b1f7ae
			errcode = yasm_print_err(p->y,
Packit b1f7ae
						 "mode.tsx: argument must be one of \"begin\", \"abort\" or \"commit\"",
Packit b1f7ae
						 -err_parse);
Packit b1f7ae
			goto error;
Packit b1f7ae
		}
Packit b1f7ae
		packet.payload.mode.leaf = pt_mol_tsx;
Packit b1f7ae
		packet.type = ppt_mode;
Packit b1f7ae
	} else if (strcmp(directive, "pip") == 0) {
Packit b1f7ae
		const char *modifier;
Packit b1f7ae
Packit b1f7ae
		errcode = parse_uint64(&packet.payload.pip.cr3, payload);
Packit b1f7ae
		if (errcode < 0) {
Packit b1f7ae
			yasm_print_err(p->y, "pip: parsing failed", errcode);
Packit b1f7ae
			goto error;
Packit b1f7ae
		}
Packit b1f7ae
		packet.type = ppt_pip;
Packit b1f7ae
		packet.payload.pip.nr = 0;
Packit b1f7ae
Packit b1f7ae
		modifier = strtok(NULL, " ,");
Packit b1f7ae
		if (modifier) {
Packit b1f7ae
			if (strcmp(modifier, "nr") == 0)
Packit b1f7ae
				packet.payload.pip.nr = 1;
Packit b1f7ae
			else {
Packit b1f7ae
				yasm_print_err(p->y, "pip: parsing failed",
Packit b1f7ae
					       -err_parse_trailing_tokens);
Packit b1f7ae
				goto error;
Packit b1f7ae
			}
Packit b1f7ae
		}
Packit b1f7ae
	} else if (strcmp(directive, "tsc") == 0) {
Packit b1f7ae
		errcode = parse_uint64(&packet.payload.tsc.tsc, payload);
Packit b1f7ae
		if (errcode < 0) {
Packit b1f7ae
			yasm_print_err(p->y, "tsc: parsing failed", errcode);
Packit b1f7ae
			goto error;
Packit b1f7ae
		}
Packit b1f7ae
		packet.type = ppt_tsc;
Packit b1f7ae
	} else if (strcmp(directive, "cbr") == 0) {
Packit b1f7ae
		errcode = parse_uint8(&packet.payload.cbr.ratio, payload);
Packit b1f7ae
		if (errcode < 0) {
Packit b1f7ae
			yasm_print_err(p->y, "cbr: parsing cbr failed",
Packit b1f7ae
				       errcode);
Packit b1f7ae
			goto error;
Packit b1f7ae
		}
Packit b1f7ae
		packet.type = ppt_cbr;
Packit b1f7ae
	} else if (strcmp(directive, "tma") == 0) {
Packit b1f7ae
		errcode = parse_tma(&packet.payload.tma.ctc,
Packit b1f7ae
				    &packet.payload.tma.fc, payload);
Packit b1f7ae
		if (errcode < 0) {
Packit b1f7ae
			yasm_print_err(p->y, "tma: parsing tma failed",
Packit b1f7ae
				       errcode);
Packit b1f7ae
			goto error;
Packit b1f7ae
		}
Packit b1f7ae
		packet.type = ppt_tma;
Packit b1f7ae
	} else if (strcmp(directive, "mtc") == 0) {
Packit b1f7ae
		errcode = parse_uint8(&packet.payload.mtc.ctc, payload);
Packit b1f7ae
		if (errcode < 0) {
Packit b1f7ae
			yasm_print_err(p->y, "mtc: parsing mtc failed",
Packit b1f7ae
				       errcode);
Packit b1f7ae
			goto error;
Packit b1f7ae
		}
Packit b1f7ae
		packet.type = ppt_mtc;
Packit b1f7ae
	} else if (strcmp(directive, "cyc") == 0) {
Packit b1f7ae
		errcode = parse_uint64(&packet.payload.cyc.value, payload);
Packit b1f7ae
		if (errcode < 0) {
Packit b1f7ae
			yasm_print_err(p->y, "cyc: parsing cyc failed",
Packit b1f7ae
				       errcode);
Packit b1f7ae
			goto error;
Packit b1f7ae
		}
Packit b1f7ae
		packet.type = ppt_cyc;
Packit b1f7ae
	} else if (strcmp(directive, "vmcs") == 0) {
Packit b1f7ae
		errcode = parse_uint64(&packet.payload.vmcs.base, payload);
Packit b1f7ae
		if (errcode < 0) {
Packit b1f7ae
			yasm_print_err(p->y, "vmcs: parsing failed", errcode);
Packit b1f7ae
			goto error;
Packit b1f7ae
		}
Packit b1f7ae
		packet.type = ppt_vmcs;
Packit b1f7ae
	} else if (strcmp(directive, "mnt") == 0) {
Packit b1f7ae
		errcode = parse_uint64(&packet.payload.mnt.payload, payload);
Packit b1f7ae
		if (errcode < 0) {
Packit b1f7ae
			yasm_print_err(p->y, "mnt: parsing failed", errcode);
Packit b1f7ae
			goto error;
Packit b1f7ae
		}
Packit b1f7ae
		packet.type = ppt_mnt;
Packit b1f7ae
	} else {
Packit b1f7ae
		errcode = yasm_print_err(p->y, "invalid syntax",
Packit b1f7ae
					 -err_parse_unknown_directive);
Packit b1f7ae
		goto error;
Packit b1f7ae
	}
Packit b1f7ae
Packit b1f7ae
	bytes_written = pt_enc_next(e, &packet);
Packit b1f7ae
	if (bytes_written < 0) {
Packit b1f7ae
		const char *errtext, *format;
Packit b1f7ae
		char *msg;
Packit b1f7ae
		size_t n;
Packit b1f7ae
Packit b1f7ae
		errtext = pt_errstr(pt_errcode(bytes_written));
Packit b1f7ae
		format = "encoder error in directive %s (status %s)";
Packit b1f7ae
		/* the length of format includes the "%s" (-2)
Packit b1f7ae
		 * characters, we add errtext (+-0) and then we need
Packit b1f7ae
		 * space for a terminating null-byte (+1).
Packit b1f7ae
		 */
Packit b1f7ae
		n = strlen(format)-4 + strlen(directive) + strlen(errtext) + 1;
Packit b1f7ae
Packit b1f7ae
		msg = malloc(n);
Packit b1f7ae
		if (!msg)
Packit b1f7ae
			errcode = yasm_print_err(p->y,
Packit b1f7ae
				       "encoder error not enough memory to show error code",
Packit b1f7ae
				       -err_pt_lib);
Packit b1f7ae
		else {
Packit b1f7ae
			sprintf(msg, format, directive, errtext);
Packit b1f7ae
			errcode = yasm_print_err(p->y, msg, -err_pt_lib);
Packit b1f7ae
			free(msg);
Packit b1f7ae
		}
Packit b1f7ae
	} else {
Packit b1f7ae
		if (pt_label_name) {
Packit b1f7ae
			errcode = l_append(p->pt_labels, pt_label_name,
Packit b1f7ae
					   p->pt_bytes_written);
Packit b1f7ae
			if (errcode < 0)
Packit b1f7ae
				goto error;
Packit b1f7ae
		}
Packit b1f7ae
		p->pt_bytes_written += bytes_written;
Packit b1f7ae
	}
Packit b1f7ae
Packit b1f7ae
error:
Packit b1f7ae
	if (errcode < 0)
Packit b1f7ae
		bytes_written = errcode;
Packit b1f7ae
	return bytes_written;
Packit b1f7ae
}
Packit b1f7ae
Packit b1f7ae
/* Starts the parsing process.
Packit b1f7ae
 *
Packit b1f7ae
 * Returns 0 on success; a negative enum errcode otherwise.
Packit b1f7ae
 * Returns -err_pt_lib if the pt encoder could not be initialized.
Packit b1f7ae
 * Returns -err_file_write if the .pt or .exp file could not be fully
Packit b1f7ae
 * written.
Packit b1f7ae
 */
Packit b1f7ae
int p_start(struct parser *p)
Packit b1f7ae
{
Packit b1f7ae
	int errcode;
Packit b1f7ae
Packit b1f7ae
	if (bug_on(!p))
Packit b1f7ae
		return -err_internal;
Packit b1f7ae
Packit b1f7ae
	errcode = yasm_parse(p->y);
Packit b1f7ae
	if (errcode < 0)
Packit b1f7ae
		return errcode;
Packit b1f7ae
Packit b1f7ae
	for (;;) {
Packit b1f7ae
		int bytes_written;
Packit b1f7ae
		struct pt_encoder *e;
Packit b1f7ae
Packit b1f7ae
		errcode = yasm_next_pt_directive(p->y, p->pd);
Packit b1f7ae
		if (errcode < 0)
Packit b1f7ae
			break;
Packit b1f7ae
Packit b1f7ae
		e = pt_alloc_encoder(p->conf);
Packit b1f7ae
		if (!e) {
Packit b1f7ae
			fprintf(stderr, "pt_alloc_encoder failed\n");
Packit b1f7ae
			errcode = -err_pt_lib;
Packit b1f7ae
			break;
Packit b1f7ae
		}
Packit b1f7ae
Packit b1f7ae
		bytes_written = p_process(p, e);
Packit b1f7ae
Packit b1f7ae
		pt_free_encoder(e);
Packit b1f7ae
Packit b1f7ae
		if (bytes_written == -stop_process) {
Packit b1f7ae
			errcode = p_gen_expfile(p);
Packit b1f7ae
			break;
Packit b1f7ae
		}
Packit b1f7ae
		if (bytes_written < 0) {
Packit b1f7ae
			errcode = bytes_written;
Packit b1f7ae
			break;
Packit b1f7ae
		}
Packit b1f7ae
		if (fwrite(p->conf->begin, 1, bytes_written, p->ptfile)
Packit b1f7ae
		    != (size_t)bytes_written) {
Packit b1f7ae
			fprintf(stderr, "write %s failed", p->ptfilename);
Packit b1f7ae
			errcode = -err_file_write;
Packit b1f7ae
			break;
Packit b1f7ae
		}
Packit b1f7ae
	}
Packit b1f7ae
Packit b1f7ae
	/* If there is no directive left, there's nothing more to do.  */
Packit b1f7ae
	if (errcode == -err_no_directive)
Packit b1f7ae
		return 0;
Packit b1f7ae
Packit b1f7ae
	return errcode;
Packit b1f7ae
}
Packit b1f7ae
Packit b1f7ae
int parse(const char *pttfile, const struct pt_config *conf)
Packit b1f7ae
{
Packit b1f7ae
	int errcode;
Packit b1f7ae
	struct parser *p;
Packit b1f7ae
Packit b1f7ae
	p = p_alloc(pttfile, conf);
Packit b1f7ae
	if (!p)
Packit b1f7ae
		return -err_no_mem;
Packit b1f7ae
Packit b1f7ae
	errcode = p_open_files(p);
Packit b1f7ae
	if (errcode < 0)
Packit b1f7ae
		goto error;
Packit b1f7ae
Packit b1f7ae
	errcode = p_start(p);
Packit b1f7ae
	p_close_files(p);
Packit b1f7ae
Packit b1f7ae
error:
Packit b1f7ae
	p_free(p);
Packit b1f7ae
	return errcode;
Packit b1f7ae
}
Packit b1f7ae
Packit b1f7ae
int parse_empty(char *payload)
Packit b1f7ae
{
Packit b1f7ae
	if (!payload)
Packit b1f7ae
		return 0;
Packit b1f7ae
Packit b1f7ae
	strtok(payload, " ");
Packit b1f7ae
	if (!payload || *payload == '\0')
Packit b1f7ae
		return 0;
Packit b1f7ae
Packit b1f7ae
	return -err_parse_trailing_tokens;
Packit b1f7ae
}
Packit b1f7ae
Packit b1f7ae
int parse_tnt(uint64_t *tnt, uint8_t *size, char *payload)
Packit b1f7ae
{
Packit b1f7ae
	char c;
Packit b1f7ae
Packit b1f7ae
	if (bug_on(!size))
Packit b1f7ae
		return -err_internal;
Packit b1f7ae
Packit b1f7ae
	if (bug_on(!tnt))
Packit b1f7ae
		return -err_internal;
Packit b1f7ae
Packit b1f7ae
	*size = 0;
Packit b1f7ae
	*tnt = 0ull;
Packit b1f7ae
Packit b1f7ae
	if (!payload)
Packit b1f7ae
		return 0;
Packit b1f7ae
Packit b1f7ae
	while (*payload != '\0') {
Packit b1f7ae
		c = *payload;
Packit b1f7ae
		payload++;
Packit b1f7ae
		if (isspace(c) || c == '.')
Packit b1f7ae
			continue;
Packit b1f7ae
		*size += 1;
Packit b1f7ae
		*tnt <<= 1;
Packit b1f7ae
		switch (c) {
Packit b1f7ae
		case 'n':
Packit b1f7ae
			break;
Packit b1f7ae
		case 't':
Packit b1f7ae
			*tnt |= 1;
Packit b1f7ae
			break;
Packit b1f7ae
		default:
Packit b1f7ae
			return -err_parse_unknown_char;
Packit b1f7ae
		}
Packit b1f7ae
	}
Packit b1f7ae
Packit b1f7ae
	return 0;
Packit b1f7ae
}
Packit b1f7ae
Packit b1f7ae
static int check_ipc(enum pt_ip_compression ipc)
Packit b1f7ae
{
Packit b1f7ae
	switch (ipc) {
Packit b1f7ae
	case pt_ipc_suppressed:
Packit b1f7ae
	case pt_ipc_update_16:
Packit b1f7ae
	case pt_ipc_update_32:
Packit b1f7ae
	case pt_ipc_update_48:
Packit b1f7ae
	case pt_ipc_sext_48:
Packit b1f7ae
	case pt_ipc_full:
Packit b1f7ae
		return 0;
Packit b1f7ae
	}
Packit b1f7ae
	return -err_parse_ipc;
Packit b1f7ae
}
Packit b1f7ae
Packit b1f7ae
int parse_ip(struct parser *p, uint64_t *ip, enum pt_ip_compression *ipc,
Packit b1f7ae
	     char *payload)
Packit b1f7ae
{
Packit b1f7ae
	int errcode;
Packit b1f7ae
	char *endptr;
Packit b1f7ae
Packit b1f7ae
	if (bug_on(!ip))
Packit b1f7ae
		return -err_internal;
Packit b1f7ae
Packit b1f7ae
	if (bug_on(!ipc))
Packit b1f7ae
		return -err_internal;
Packit b1f7ae
Packit b1f7ae
	*ipc = pt_ipc_suppressed;
Packit b1f7ae
	*ip = 0;
Packit b1f7ae
Packit b1f7ae
	payload = strtok(payload, " :");
Packit b1f7ae
	if (!payload || *payload == '\0')
Packit b1f7ae
		return -err_parse_no_args;
Packit b1f7ae
Packit b1f7ae
	*ipc = (enum pt_ip_compression) strtol(payload, &endptr, 0);
Packit b1f7ae
	if (payload == endptr || *endptr != '\0')
Packit b1f7ae
		return -err_parse_ipc;
Packit b1f7ae
Packit b1f7ae
	/* is ipc valid?  */
Packit b1f7ae
	errcode = check_ipc(*ipc);
Packit b1f7ae
	if (errcode < 0)
Packit b1f7ae
		return errcode;
Packit b1f7ae
Packit b1f7ae
	payload = strtok(NULL, " :");
Packit b1f7ae
	if (!payload)
Packit b1f7ae
		return -err_parse_ip_missing;
Packit b1f7ae
Packit b1f7ae
	/* can be resolved to a label?  */
Packit b1f7ae
	if (*payload == '%') {
Packit b1f7ae
		if (!p)
Packit b1f7ae
			return -err_internal;
Packit b1f7ae
Packit b1f7ae
		errcode = yasm_lookup_label(p->y, ip, payload + 1);
Packit b1f7ae
		if (errcode < 0)
Packit b1f7ae
			return errcode;
Packit b1f7ae
	} else {
Packit b1f7ae
		/* can be parsed as address?  */
Packit b1f7ae
		errcode = str_to_uint64(payload, ip, 0);
Packit b1f7ae
		if (errcode < 0)
Packit b1f7ae
			return errcode;
Packit b1f7ae
	}
Packit b1f7ae
Packit b1f7ae
	/* no more tokens left.  */
Packit b1f7ae
	payload = strtok(NULL, " ");
Packit b1f7ae
	if (payload)
Packit b1f7ae
		return -err_parse_trailing_tokens;
Packit b1f7ae
Packit b1f7ae
	return 0;
Packit b1f7ae
}
Packit b1f7ae
Packit b1f7ae
int parse_uint64(uint64_t *x, char *payload)
Packit b1f7ae
{
Packit b1f7ae
	int errcode;
Packit b1f7ae
Packit b1f7ae
	if (bug_on(!x))
Packit b1f7ae
		return -err_internal;
Packit b1f7ae
Packit b1f7ae
	payload = strtok(payload, " ,");
Packit b1f7ae
	if (!payload)
Packit b1f7ae
		return -err_parse_no_args;
Packit b1f7ae
Packit b1f7ae
	errcode = str_to_uint64(payload, x, 0);
Packit b1f7ae
	if (errcode < 0)
Packit b1f7ae
		return errcode;
Packit b1f7ae
Packit b1f7ae
	return 0;
Packit b1f7ae
}
Packit b1f7ae
Packit b1f7ae
int parse_uint32(uint32_t *x, char *payload)
Packit b1f7ae
{
Packit b1f7ae
	int errcode;
Packit b1f7ae
Packit b1f7ae
	if (bug_on(!x))
Packit b1f7ae
		return -err_internal;
Packit b1f7ae
Packit b1f7ae
	payload = strtok(payload, " ,");
Packit b1f7ae
	if (!payload)
Packit b1f7ae
		return -err_parse_no_args;
Packit b1f7ae
Packit b1f7ae
	errcode = str_to_uint32(payload, x, 0);
Packit b1f7ae
	if (errcode < 0)
Packit b1f7ae
		return errcode;
Packit b1f7ae
Packit b1f7ae
	return 0;
Packit b1f7ae
}
Packit b1f7ae
Packit b1f7ae
int parse_uint16(uint16_t *x, char *payload)
Packit b1f7ae
{
Packit b1f7ae
	int errcode;
Packit b1f7ae
Packit b1f7ae
	if (bug_on(!x))
Packit b1f7ae
		return -err_internal;
Packit b1f7ae
Packit b1f7ae
	payload = strtok(payload, " ,");
Packit b1f7ae
	if (!payload)
Packit b1f7ae
		return -err_parse_no_args;
Packit b1f7ae
Packit b1f7ae
	errcode = str_to_uint16(payload, x, 0);
Packit b1f7ae
	if (errcode < 0)
Packit b1f7ae
		return errcode;
Packit b1f7ae
Packit b1f7ae
	return 0;
Packit b1f7ae
}
Packit b1f7ae
Packit b1f7ae
int parse_uint8(uint8_t *x, char *payload)
Packit b1f7ae
{
Packit b1f7ae
	int errcode;
Packit b1f7ae
Packit b1f7ae
	if (bug_on(!x))
Packit b1f7ae
		return -err_internal;
Packit b1f7ae
Packit b1f7ae
	payload = strtok(payload, " ,");
Packit b1f7ae
	if (!payload)
Packit b1f7ae
		return -err_parse_no_args;
Packit b1f7ae
Packit b1f7ae
	errcode = str_to_uint8(payload, x, 0);
Packit b1f7ae
	if (errcode < 0)
Packit b1f7ae
		return errcode;
Packit b1f7ae
Packit b1f7ae
	return 0;
Packit b1f7ae
}
Packit b1f7ae
Packit b1f7ae
int parse_tma(uint16_t *ctc, uint16_t *fc, char *payload)
Packit b1f7ae
{
Packit b1f7ae
	char *endptr;
Packit b1f7ae
	long int i;
Packit b1f7ae
Packit b1f7ae
	if (bug_on(!ctc || !fc))
Packit b1f7ae
		return -err_internal;
Packit b1f7ae
Packit b1f7ae
	payload = strtok(payload, ",");
Packit b1f7ae
	if (!payload || *payload == '\0')
Packit b1f7ae
		return -err_parse_no_args;
Packit b1f7ae
Packit b1f7ae
	i = strtol(payload, &endptr, 0);
Packit b1f7ae
	if (payload == endptr || *endptr != '\0')
Packit b1f7ae
		return -err_parse_int;
Packit b1f7ae
Packit b1f7ae
	if (i > 0xffffl)
Packit b1f7ae
		return -err_parse_int_too_big;
Packit b1f7ae
Packit b1f7ae
	*ctc = (uint16_t)i;
Packit b1f7ae
Packit b1f7ae
	payload = strtok(NULL, " ,");
Packit b1f7ae
	if (!payload)
Packit b1f7ae
		return -err_parse_no_args;
Packit b1f7ae
Packit b1f7ae
	i = strtol(payload, &endptr, 0);
Packit b1f7ae
	if (payload == endptr || *endptr != '\0')
Packit b1f7ae
		return -err_parse_int;
Packit b1f7ae
Packit b1f7ae
	if (i > 0xffffl)
Packit b1f7ae
		return -err_parse_int_too_big;
Packit b1f7ae
Packit b1f7ae
	*fc = (uint16_t)i;
Packit b1f7ae
Packit b1f7ae
	/* no more tokens left.  */
Packit b1f7ae
	payload = strtok(NULL, " ");
Packit b1f7ae
	if (payload)
Packit b1f7ae
		return -err_parse_trailing_tokens;
Packit b1f7ae
Packit b1f7ae
	return 0;
Packit b1f7ae
}