#line 1 "../../libdrgn/drgn_program_parse_vmcoreinfo.inc.strswitch"
static struct drgn_error *parse_vmcoreinfo_u64(const char *value,
					       const char *newline, int base,
					       uint64_t *ret)
{
	errno = 0;
	char *end;
	*ret = strtoull(value, &end, base);
	if (errno == ERANGE) {
		return drgn_error_create(DRGN_ERROR_OVERFLOW,
					 "number in VMCOREINFO is too large");
	} else if (errno || end == value || end != newline) {
		return drgn_error_create(DRGN_ERROR_OTHER,
					 "number in VMCOREINFO is invalid");
	}
	return NULL;
}

struct drgn_error *drgn_program_parse_vmcoreinfo(struct drgn_program *prog,
						 const char *desc,
						 size_t descsz)
{
	struct drgn_error *err;
	for (const char *line = desc, *end = &desc[descsz], *newline;
	     (newline = memchr(line, '\n', end - line));
	     line = newline + 1) {
		const char *equals = memchr(line, '=', newline - line);
		if (!equals)
			continue;

		const char *value = equals + 1;
#line 33 "drgn_program_parse_vmcoreinfo.inc"
		/* Generated by libdrgn/build-aux/gen_strswitch.py. */
		switch (1) {
		default: {
			#define memswitch0_args(ptr, len) \
				const void *memswitch0_ptr = (ptr); \
				const char *memswitch0_str = memswitch0_ptr; \
				size_t memswitch0_len = (len);
			memswitch0_args(
#line 31 "../../libdrgn/drgn_program_parse_vmcoreinfo.inc.strswitch"
		            line, equals - line
#line 44 "drgn_program_parse_vmcoreinfo.inc"
			)
			#undef memswitch0_args
			if (memswitch0_len == 8) {
				if (memcmp(&memswitch0_str[0], "PAGESIZE", sizeof("PAGESIZE") - 1) == 0) {
					memswitch0_case1:
#line 43 "../../libdrgn/drgn_program_parse_vmcoreinfo.inc.strswitch"
			err = parse_vmcoreinfo_u64(value, newline, 0,
						   &prog->vmcoreinfo.page_size);
			if (err)
				return err;
			break;
#line 56 "drgn_program_parse_vmcoreinfo.inc"
					goto memswitch0_case2;
				}
			} else if (memswitch0_len == 9) {
				if (memcmp(&memswitch0_str[0], "OSRELEASE", sizeof("OSRELEASE") - 1) == 0) {
#line 33 "../../libdrgn/drgn_program_parse_vmcoreinfo.inc.strswitch"
			if ((size_t)(newline - value) >=
			    sizeof(prog->vmcoreinfo.osrelease)) {
				return drgn_error_create(DRGN_ERROR_OTHER,
							 "OSRELEASE in VMCOREINFO is too long");
			}
			memcpy(prog->vmcoreinfo.osrelease, value,
			       newline - value);
			prog->vmcoreinfo.osrelease[newline - value] = '\0';
			break;
#line 71 "drgn_program_parse_vmcoreinfo.inc"
					goto memswitch0_case1;
				}
			} else if (memswitch0_len == 12) {
				if (memcmp(&memswitch0_str[0], "KERNELOFFSET", sizeof("KERNELOFFSET") - 1) == 0) {
					memswitch0_case2:
#line 49 "../../libdrgn/drgn_program_parse_vmcoreinfo.inc.strswitch"
			err = parse_vmcoreinfo_u64(value, newline, 16,
						   &prog->vmcoreinfo.kaslr_offset);
			if (err)
				return err;
			break;
#line 83 "drgn_program_parse_vmcoreinfo.inc"
					goto memswitch0_case3;
				}
			} else if (memswitch0_len == 15) {
				if (memcmp(&memswitch0_str[0], "NUMBER(VA_BITS)", sizeof("NUMBER(VA_BITS)") - 1) == 0) {
					memswitch0_case7:
#line 82 "../../libdrgn/drgn_program_parse_vmcoreinfo.inc.strswitch"
			err = parse_vmcoreinfo_u64(value, newline, 0,
						   &prog->vmcoreinfo.va_bits);
			if (err)
				return err;
			break;
#line 95 "drgn_program_parse_vmcoreinfo.inc"
				}
			} else if (memswitch0_len == 19) {
				if (memcmp(&memswitch0_str[0], "LENGTH(mem_section)", sizeof("LENGTH(mem_section)") - 1) == 0) {
					memswitch0_case4:
#line 61 "../../libdrgn/drgn_program_parse_vmcoreinfo.inc.strswitch"
			err = parse_vmcoreinfo_u64(value, newline, 0,
						   &prog->vmcoreinfo.mem_section_length);
			if (err)
				return err;
			break;
#line 106 "drgn_program_parse_vmcoreinfo.inc"
					goto memswitch0_case5;
				}
			} else if (memswitch0_len == 21) {
				if (memcmp(&memswitch0_str[0], "NUMBER(KERNELPACMASK)", sizeof("NUMBER(KERNELPACMASK)") - 1) == 0) {
					memswitch0_case6:
#line 76 "../../libdrgn/drgn_program_parse_vmcoreinfo.inc.strswitch"
			err = parse_vmcoreinfo_u64(value, newline, 16,
						   &prog->aarch64_insn_pac_mask);
			if (err)
				return err;
			break;
#line 118 "drgn_program_parse_vmcoreinfo.inc"
					goto memswitch0_case7;
				}
			} else if (memswitch0_len == 22) {
				if (memcmp(&memswitch0_str[0], "SYMBOL(swapper_pg_dir)", sizeof("SYMBOL(swapper_pg_dir)") - 1) == 0) {
					memswitch0_case3:
#line 55 "../../libdrgn/drgn_program_parse_vmcoreinfo.inc.strswitch"
			err = parse_vmcoreinfo_u64(value, newline, 16,
						   &prog->vmcoreinfo.swapper_pg_dir);
			if (err)
				return err;
			break;
#line 130 "drgn_program_parse_vmcoreinfo.inc"
					goto memswitch0_case4;
				}
			} else if (memswitch0_len == 26) {
				if (memcmp(&memswitch0_str[0], "NUMBER(pgtable_l5_enabled)", sizeof("NUMBER(pgtable_l5_enabled)") - 1) == 0) {
					memswitch0_case5:
#line 67 "../../libdrgn/drgn_program_parse_vmcoreinfo.inc.strswitch"
		{
			uint64_t tmp;
			err = parse_vmcoreinfo_u64(value, newline, 0, &tmp);
			if (err)
				return err;
			prog->vmcoreinfo.pgtable_l5_enabled = tmp;
			break;
		}
#line 145 "drgn_program_parse_vmcoreinfo.inc"
					goto memswitch0_case6;
				}
			}
		}
		}
#line 88 "../../libdrgn/drgn_program_parse_vmcoreinfo.inc.strswitch"
	}
	if (!prog->vmcoreinfo.osrelease[0]) {
		return drgn_error_create(DRGN_ERROR_OTHER,
					 "VMCOREINFO does not contain valid OSRELEASE");
	}
	if (!is_power_of_two(prog->vmcoreinfo.page_size)) {
		return drgn_error_create(DRGN_ERROR_OTHER,
					 "VMCOREINFO does not contain valid PAGESIZE");
	}
	prog->vmcoreinfo.page_shift = ctz(prog->vmcoreinfo.page_size);
	if (!prog->vmcoreinfo.swapper_pg_dir) {
		return drgn_error_create(DRGN_ERROR_OTHER,
					 "VMCOREINFO does not contain valid swapper_pg_dir");
	}
	// Everything else is optional.
	return NULL;
}
