code:
/* $NetBSD: term_private.h,v 1.19 2020/06/21 15:05:23 roy Exp $ */

/*
 * Copyright (c) 2009, 2010, 2013, 2020 The NetBSD Foundation, Inc.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Roy Marples.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _TERM_PRIVATE_H_
#define	_TERM_PRIVATE_H_

/* This header should only be used by libterminfo, tic and infocmp. */

/* The terminfo database structure is private to us,
 * so it's documented here.
 *
 * Version 1 - types 1 and 2.
 * terminfo defines the largest number as 32767 and the largest
 * compiled entry as 4093 bytes long. Negative numbers are not allowed.
 * Thus, we store all numbers as uint16_t, including string length.
 * We reserve negative numbers -1 and -2 to mean absent or cancelled.
 * All strings are prefixed by length, including the null terminator.
 * The largest string length we can handle is 65535 bytes,
 * including the null terminator.
 * The largest capability block we can handle is 65535 bytes.
 *
 * Version 2 - type 3
 * Extends terminfo numbers upto 2147483647 by storing the value as a uint32_t.
 * This means that we exceed the current terminfo defined limits in every way.
 *
 * Type 1 capabilities are defined as:
 * header byte (always 1)
 * name
 * description,
 * cap length, num flags, index, char,
 * cap length, num numbers, index, number,
 * cap length, num strings, index, string,
 * cap length, num undefined caps, name, type (char), flag, number, string
 *
 * Type 2 entries are aliases and defined as:
 * header byte (always 2)
 * 32bit id of the corresponding terminal in the file
 * name
 *
 * Type 3 extends Type 1 so that it can store terminfo numbers
 * as uint32_t. All other numerics are still stored as uint16_t.
 *
 * The database itself is created using cdbw(3) and the numbers are
 * always stored as little endian.
 */

#include <sys/types.h>
#include <assert.h>
#include <limits.h>
#include <stdint.h>
#include <string.h>

#define _TERMINFO
#define TERMINFO_RTYPE_O1	1
#define TERMINFO_ALIAS		2
#define TERMINFO_RTYPE		3

/* , and | are the two print characters now allowed
 * in terminfo aliases or long descriptions.
 * As | is generally used to delimit aliases inside the
 * description, we use a comma. */
#define TERMINFO_VDELIM		','
#define TERMINFO_VDELIMSTR	","

/* We use the same ncurses tic macros so that our data is identical
 * when a caller uses the long name macros to access te terminfo data
 * directly. */
#define ABSENT_BOOLEAN		((signed char)-1)       /* 255 */
#define ABSENT_NUMERIC		(-1)
#define ABSENT_STRING		(char *)0
#define CANCELLED_BOOLEAN	((signed char)-2)       /* 254 */
#define CANCELLED_NUMERIC	(-2)
#define CANCELLED_STRING	(char *)(-1)
#define VALID_BOOLEAN(s) ((unsigned char)(s) <= 1)	/* reject "-1" */
#define VALID_NUMERIC(s) ((s) >= 0)
#define VALID_STRING(s)  ((s) != CANCELLED_STRING && (s) != ABSENT_STRING)

typedef struct {
	const char *id;
	char type;
	char flag;
	int num;
	const char *str;
} TERMUSERDEF;

typedef struct {
	int fildes;
	/* We need to expose these so that the macros work */
	const char *name;
	const char *desc;
	signed char *flags;
	int *nums;
	const char **strs;
	/* Storage area for terminfo data */
	char *_area;
	size_t _arealen;
	size_t _nuserdefs;
	TERMUSERDEF *_userdefs;
	/* So we don't rely on the global ospeed */
	short _ospeed;
	/* Output buffer for tparm */
	char *_buf;
	size_t _buflen;
	size_t _bufpos;
	/* A-Z static variables for tparm  */
	long _snums[26];
	/* aliases of the terminal, | separated */
	const char *_alias;
} TERMINAL;

extern const char *	_ti_database;

ssize_t		_ti_flagindex(const char *);
ssize_t		_ti_numindex(const char *);
ssize_t		_ti_strindex(const char *);
const char *	_ti_flagid(ssize_t);
const char *	_ti_numid(ssize_t);
const char *	_ti_strid(ssize_t);
int		_ti_getterm(TERMINAL *, const char *, int);
void		_ti_setospeed(TERMINAL *);

/* libterminfo can compile terminfo strings too */
#define TIC_WARNING	(1 << 0)
#define TIC_DESCRIPTION	(1 << 1)
#define TIC_ALIAS	(1 << 2)
#define TIC_COMMENT	(1 << 3)
#define TIC_EXTRA	(1 << 4)
#define TIC_COMPAT_V1	(1 << 5)

typedef struct {
	char *buf;
	size_t buflen;
	size_t bufpos;
	size_t entries;
} TBUF;

typedef struct {
	char *name;
	char *alias;
	char *desc;
	int  rtype;
	TBUF flags;
	TBUF nums;
	TBUF strs;
	TBUF extras;
} TIC;

#define _ti_numsize(tic) \
    ((tic)->rtype == TERMINFO_RTYPE_O1 ? sizeof(uint16_t) : sizeof(uint32_t))

int _ti_promote(TIC *);
char *_ti_grow_tbuf(TBUF *, size_t);
char *_ti_get_token(char **, char);
const char *_ti_find_cap(TIC *, TBUF *, char,  short);
const char *_ti_find_extra(TIC *, TBUF *, const char *);
char *_ti_getname(int, const char *);
size_t _ti_store_extra(TIC *, int, const char *, char, char, int,
    const char *, size_t, int);
TIC *_ti_compile(char *, int);
ssize_t _ti_flatten(uint8_t **, const TIC *);
void _ti_freetic(TIC *);

int _ti_encode_buf_id_num(TBUF *, int, int, size_t);
int _ti_encode_buf_id_count_str(TBUF *, int, const void *, size_t);
int _ti_encode_buf_id_flags(TBUF *, int, int);

#define TPARM_MAX 9	/* not likely to change */
int _ti_parm_analyse(const char *, int *, int);

static inline int
_ti_decode_16(const char **cap)
{
	uint8_t *buf = (uint8_t *)*cap;

	*cap += 2;
	return buf[0] | buf[1] << 8;
}

static inline int
_ti_decode_32(const char **cap)
{
	uint8_t *buf = (uint8_t *)*cap;

	*cap += 4;
	return buf[0] | buf[1] << 8 | buf[2] << 16 | buf[3] << 24;
}

static inline int
_ti_decode_num(const char **cap, int rtype)
{
	if (rtype == TERMINFO_RTYPE_O1) {
		return _ti_decode_16(cap);
	} else {
		return _ti_decode_32(cap);
	}
}

static inline void
_ti_encode_16(char **cap, size_t num)
{
	uint8_t *buf = (uint8_t *)*cap;

	assert(num <= UINT16_MAX);
	buf[0] = num;
	buf[1] = num >> 8;
	*cap += 2;
}

static inline void
_ti_encode_32(char **cap, size_t num)
{
	uint8_t *buf = (uint8_t *)*cap;

	assert(num <= UINT32_MAX);
	buf[0] = num;
	buf[1] = num >> 8;
	buf[2] = num >> 16;
	buf[3] = num >> 24;
	*cap += 4;
}

static inline void
_ti_encode_str(char **cap, const void *buf, size_t len)
{
	memcpy(*cap, buf, len);
	*cap += len;
}

static inline void
_ti_encode_count_str(char **cap, const char *name, size_t len)
{
	_ti_encode_16(cap, (uint16_t)len);
	if (name == NULL)
		return;
	_ti_encode_str(cap, name, len);
}

static inline void
_ti_encode_buf_16(TBUF *tbuf, size_t num)
{
	char *buf = tbuf->buf + tbuf->bufpos;

	assert(num <= UINT16_MAX);
	_ti_encode_16(&buf, num);
	tbuf->bufpos += 2;
}

static inline void
_ti_encode_buf_32(TBUF *tbuf, size_t num)
{
	char *buf = tbuf->buf + tbuf->bufpos;

	assert(num <= UINT32_MAX);
	_ti_encode_32(&buf, num);
	tbuf->bufpos += 4;
}

static inline void
_ti_encode_buf_count_str(TBUF *tbuf, const void *buf, size_t len)
{
	_ti_encode_buf_16(tbuf, len);
	memcpy(tbuf->buf + tbuf->bufpos, buf, len);
	tbuf->bufpos += len;
}

static inline void
_ti_encode_buf_num(TBUF *tbuf, int num, int rtype)
{
	if (rtype == TERMINFO_RTYPE_O1) {
		if (num > INT16_MAX)
			num = INT16_MAX;
		_ti_encode_buf_16(tbuf, (uint16_t)num);
	} else {
		if (num > INT32_MAX)
			num = INT32_MAX;
		_ti_encode_buf_32(tbuf, (uint32_t)num);
	}
}

#endif


code:
.\"	$NetBSD: tic.1,v 1.13 2017/02/22 13:43:15 abhinav Exp $
.\"
.\" Copyright (c) 2009, 2010 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to The NetBSD Foundation
.\" by Roy Marples.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\"    notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\"    notice, this list of conditions and the following disclaimer in the
.\"    documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd June 3, 2012
.Dt TIC 1
.Os
.Sh NAME
.Nm tic
.Nd terminfo compiler
.Sh SYNOPSIS
.Nm tic
.Op Fl acSsx
.Op Fl o Ar file
.Ar source
.Op Ar term1 term2 ...
.Sh DESCRIPTION
The
.Nm
utility compiles
.Xr terminfo 5
source into a database for use by other programs.
The created database path name is the same as the source but with .cdb appended.
.Pp
The following options are available:
.Bl -tag -width Fl
.It Fl a
Do not discard commented out capabilities.
.It Fl c
Only check for errors, don't write the final database.
.It Fl o Ar file
Write the database to
.Ar file
instead of
.Ar source Ns .cdb .
.It Fl S
For
.Ar term1 , term2 , ...
output a C structure containing name, compiled description, and compiled size.
This can be used to embed terminal descriptions into a program.
.It Fl s
Display the number of terminal descriptions written to the database.
.It Fl x
Include non standard capabilities defined in the
.Ar source .
.El
.Ss Extensions To Terminfo
When
.Nm
discovers a
.Sy use Ns = Ns Va term
capability, the terminal description for
.Va term
is merged in.
Capabilities do not overwrite previously discovered ones and capabilities
ending with @ are marked as absent so the terminal does not inherit the
capability from
.Sy use Ns d
terminals.
.Sh EXIT STATUS
.Ex -std tic
.Sh EXAMPLES
To maintain your private terminfo definitions, if the system supplied
ones do not support your terminal:
.Bd -literal -offset indent
.Ic tic ~/.terminfo
.Ed
.Sh SEE ALSO
.Xr infocmp 1 ,
.Xr tput 1 ,
.Xr curses 3 ,
.Xr terminfo 5
.Sh STANDARDS
The
.Nm
utility works with terminfo files that conform to the
.St -xcurses4.2
standard.
.Sh AUTHORS
.An Roy Marples Aq Mt roy@NetBSD.org

repo_name: misc/slterm

license: mit


code:
/* $NetBSD: tic.c,v 1.40 2020/03/30 00:09:06 roy Exp $ */

/*
 * Copyright (c) 2009, 2010, 2020 The NetBSD Foundation, Inc.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Roy Marples.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif

#include <sys/types.h>
#include <sys/queue.h>
#include <sys/stat.h>

#include <cdbw.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <getopt.h>
#include <limits.h>
#include <fcntl.h>
#include <search.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <term_private.h>
#include <term.h>
#include <unistd.h>

#define	HASH_SIZE	16384	/* 2012-06-01: 3600 entries */

typedef struct term {
	STAILQ_ENTRY(term) next;
	char *name;
	TIC *tic;
	uint32_t id;
	struct term *base_term;
} TERM;
static STAILQ_HEAD(, term) terms = STAILQ_HEAD_INITIALIZER(terms);

static int error_exit;
static int Sflag;
static size_t nterm, nalias;

static void
dowarn(const char *fmt, ...)
{
	va_list va;

	error_exit = 1;
	va_start(va, fmt);
	vwarnx(fmt, va);
	va_end(va);
}

static char *
grow_tbuf(TBUF *tbuf, size_t len)
{
	char *buf;

	buf = _ti_grow_tbuf(tbuf, len);
	if (buf == NULL)
		err(EXIT_FAILURE, "_ti_grow_tbuf");
	return buf;
}

static int
save_term(struct cdbw *db, TERM *term)
{
	uint8_t *buf;
	ssize_t len;
	size_t slen = strlen(term->name) + 1;

	if (term->base_term != NULL) {
		char *cap;
		len = (ssize_t)(1 + sizeof(uint32_t) + sizeof(uint16_t) + slen);
		buf = malloc(len);
		if (!buf)
			err(EXIT_FAILURE, NULL);
		cap = (char *)buf;
		*cap++ = TERMINFO_ALIAS;
		_ti_encode_32(&cap, term->base_term->id);
		_ti_encode_count_str(&cap, term->name, slen);
		if (cdbw_put(db, term->name, slen, buf, len))
			err(EXIT_FAILURE, "cdbw_put");
		free(buf);
		return 0;
	}

	len = _ti_flatten(&buf, term->tic);
	if (len == -1)
		return -1;

	if (cdbw_put_data(db, buf, len, &term->id))
		err(EXIT_FAILURE, "cdbw_put_data");
	if (cdbw_put_key(db, term->name, slen, term->id))
		err(EXIT_FAILURE, "cdbw_put_key");
	free(buf);
	return 0;
}

static TERM *
find_term(const char *name)
{
	ENTRY elem, *elemp;

	elem.key = (char *)name;
	elem.data = NULL;
	elemp = hsearch(elem, FIND);
	return elemp ? (TERM *)elemp->data : NULL;
}

static TERM *
find_newest_term(const char *name)
{
	char *lname;
	TERM *term;

	lname = _ti_getname(TERMINFO_RTYPE, name);
	if (lname == NULL)
		return NULL;
	term = find_term(lname);
	free(lname);
	if (term == NULL)
		term = find_term(name);
	return term;
}

static TERM *
store_term(const char *name, TERM *base_term)
{
	TERM *term;
	ENTRY elem;

	term = calloc(1, sizeof(*term));
	if (!term)
		err(EXIT_FAILURE, NULL);
	term->name = strdup(name);
	if (!term->name)
		err(EXIT_FAILURE, NULL);
	STAILQ_INSERT_TAIL(&terms, term, next);
	elem.key = strdup(name);
	if (!elem.key)
		err(EXIT_FAILURE, NULL);
	elem.data = term;
	hsearch(elem, ENTER);

	term->base_term = base_term;
	if (base_term != NULL)
		nalias++;
	else
		nterm++;

	return term;
}

static void
alias_terms(TERM *term)
{
	char *p, *e, *alias;

	/* Create aliased terms */
	if (term->tic->alias == NULL)
		return;

	alias = p = strdup(term->tic->alias);
	if (!alias)
		err(EXIT_FAILURE, NULL);
	while (p != NULL && *p != '\0') {
		e = strchr(p, '|');
		if (e != NULL)
			*e++ = '\0';
		/* No need to lengthcheck the alias because the main
		 * terminfo description already stores all the aliases
		 * in the same length field as the alias. */
		if (find_term(p) != NULL) {
			dowarn("%s: has alias for already assigned"
			    " term %s", term->tic->name, p);
		} else {
			store_term(p, term);
		}
		p = e;
	}
	free(alias);
}

static int
process_entry(TBUF *buf, int flags)
{
	TERM *term;
	TIC *tic;
#ifdef TERMINFO_COMPAT
	TBUF sbuf = *buf;
#endif

	if (buf->bufpos == 0)
		return 0;
	/* Terminate the string */
	buf->buf[buf->bufpos - 1] = '\0';
	/* First rewind the buffer for new entries */
	buf->bufpos = 0;

	if (isspace((unsigned char)*buf->buf))
		return 0;

	tic = _ti_compile(buf->buf, flags);
	if (tic == NULL)
		return 0;

	if (find_term(tic->name) != NULL) {
		dowarn("%s: duplicate entry", tic->name);
		_ti_freetic(tic);
		return 0;
	}
	term = store_term(tic->name, NULL);
	term->tic = tic;
	alias_terms(term);

#ifdef TERMINFO_COMPAT
	if (tic->rtype == TERMINFO_RTYPE)
		return process_entry(&sbuf, flags | TIC_COMPAT_V1);
#endif

	return 0;
}

static void
merge(TIC *rtic, TIC *utic, int flags)
{
	char flag, type;
	const char *cap, *code, *str;
	short ind, len;
	int num;
	size_t n;

	if (rtic->rtype < utic->rtype)
		errx(EXIT_FAILURE, "merge rtype diff (%s:%d into %s:%d)",
		    utic->name, utic->rtype, rtic->name, rtic->rtype);

	cap = utic->flags.buf;
	for (n = utic->flags.entries; n > 0; n--) {
		ind = _ti_decode_16(&cap);
		flag = *cap++;
		if (VALID_BOOLEAN(flag) &&
		    _ti_find_cap(rtic, &rtic->flags, 'f', ind) == NULL)
		{
			if (!_ti_encode_buf_id_flags(&rtic->flags, ind, flag))
				err(EXIT_FAILURE, "encode flag");
		}
	}

	cap = utic->nums.buf;
	for (n = utic->nums.entries; n > 0; n--) {
		ind = _ti_decode_16(&cap);
		num = _ti_decode_num(&cap, utic->rtype);
		if (VALID_NUMERIC(num) &&
		    _ti_find_cap(rtic, &rtic->nums, 'n', ind) == NULL)
		{
			if (!_ti_encode_buf_id_num(&rtic->nums, ind, num,
			    _ti_numsize(rtic)))
				err(EXIT_FAILURE, "encode num");
		}
	}

	cap = utic->strs.buf;
	for (n = utic->strs.entries; n > 0; n--) {
		ind = _ti_decode_16(&cap);
		len = _ti_decode_16(&cap);
		if (len > 0 &&
		    _ti_find_cap(rtic, &rtic->strs, 's', ind) == NULL)
		{
			if (!_ti_encode_buf_id_count_str(&rtic->strs, ind, cap,
			    len))
				err(EXIT_FAILURE, "encode str");
		}
		cap += len;
	}

	cap = utic->extras.buf;
	for (n = utic->extras.entries; n > 0; n--) {
		num = _ti_decode_16(&cap);
		code = cap;
		cap += num;
		type = *cap++;
		flag = 0;
		str = NULL;
		switch (type) {
		case 'f':
			flag = *cap++;
			if (!VALID_BOOLEAN(flag))
				continue;
			break;
		case 'n':
			num = _ti_decode_num(&cap, utic->rtype);
			if (!VALID_NUMERIC(num))
				continue;
			break;
		case 's':
			num = _ti_decode_16(&cap);
			str = cap;
			cap += num;
			if (num == 0)
				continue;
			break;
		}
		_ti_store_extra(rtic, 0, code, type, flag, num, str, num,
		    flags);
	}
}

#ifdef TERMINFO_COMPAT
static int
dup_tbuf(TBUF *dst, const TBUF *src)
{

	if (src->buflen == 0)
		return 0;
	dst->buf = malloc(src->buflen);
	if (dst->buf == NULL)
		return -1;
	dst->buflen = src->buflen;
	memcpy(dst->buf, src->buf, dst->buflen);
	dst->bufpos = src->bufpos;
	dst->entries = src->entries;
	return 0;
}

static int
promote(TIC *rtic, TIC *utic)
{
	TERM *nrterm = find_newest_term(rtic->name);
	TERM *nuterm = find_newest_term(utic->name);
	TERM *term;
	TIC *tic;

	if (nrterm == NULL || nuterm == NULL)
		return -1;
	if (nrterm->tic->rtype >= nuterm->tic->rtype)
		return 0;

	tic = calloc(1, sizeof(*tic));
	if (tic == NULL)
		return -1;

	tic->name = _ti_getname(TERMINFO_RTYPE, rtic->name);
	if (tic->name == NULL)
		goto err;
	if (rtic->alias != NULL) {
		tic->alias = strdup(rtic->alias);
		if (tic->alias == NULL)
			goto err;
	}
	if (rtic->desc != NULL) {
		tic->desc = strdup(rtic->desc);
		if (tic->desc == NULL)
			goto err;
	}

	tic->rtype = rtic->rtype;
	if (dup_tbuf(&tic->flags, &rtic->flags) == -1)
		goto err;
	if (dup_tbuf(&tic->nums, &rtic->nums) == -1)
		goto err;
	if (dup_tbuf(&tic->strs, &rtic->strs) == -1)
		goto err;
	if (dup_tbuf(&tic->extras, &rtic->extras) == -1)
		goto err;
	if (_ti_promote(tic) == -1)
		goto err;

	term = store_term(tic->name, NULL);
	if (term == NULL)
		goto err;

	term->tic = tic;
	alias_terms(term);
	return 0;

err:
	free(tic->flags.buf);
	free(tic->nums.buf);
	free(tic->strs.buf);
	free(tic->extras.buf);
	free(tic->desc);
	free(tic->alias);
	free(tic->name);
	free(tic);
	return -1;
}
#endif

static size_t
merge_use(int flags)
{
	size_t skipped, merged, memn;
	const char *cap;
	char *name, *basename;
	uint16_t num;
	TIC *rtic, *utic;
	TERM *term, *uterm;
#ifdef TERMINFO_COMPAT
	bool promoted;
#endif

	skipped = merged = 0;
	STAILQ_FOREACH(term, &terms, next) {
		if (term->base_term != NULL)
			continue;
		rtic = term->tic;
		basename = _ti_getname(TERMINFO_RTYPE_O1, rtic->name);
#ifdef TERMINFO_COMPAT
		promoted = false;
#endif
		while ((cap = _ti_find_extra(rtic, &rtic->extras, "use"))
		    != NULL) {
			if (*cap++ != 's') {
				dowarn("%s: use is not string", rtic->name);
				break;
			}
			cap += sizeof(uint16_t);
			if (strcmp(basename, cap) == 0) {
				dowarn("%s: uses itself", rtic->name);
				goto remove;
			}
			name = _ti_getname(rtic->rtype, cap);
			if (name == NULL) {
				dowarn("%s: ???: %s", rtic->name, cap);
				goto remove;
			}
			uterm = find_term(name);
			free(name);
			if (uterm == NULL)
				uterm = find_term(cap);
			if (uterm != NULL && uterm->base_term != NULL)
				uterm = uterm->base_term;
			if (uterm == NULL) {
				dowarn("%s: no use record for %s",
				    rtic->name, cap);
				goto remove;
			}
			utic = uterm->tic;
			if (strcmp(utic->name, rtic->name) == 0) {
				dowarn("%s: uses itself", rtic->name);
				goto remove;
			}
			if (_ti_find_extra(utic, &utic->extras, "use")
			    != NULL) {
				skipped++;
				break;
			}

#ifdef TERMINFO_COMPAT
			/* If we need to merge in a term that requires
			 * this term to be promoted, we need to duplicate
			 * this term, promote it and append it to our list. */
			if (!promoted && rtic->rtype != TERMINFO_RTYPE) {
				if (promote(rtic, utic) == -1)
					err(EXIT_FAILURE, "promote");
				promoted = true;
			}
#endif

			merge(rtic, utic, flags);
	remove:
			/* The pointers may have changed, find the use again */
			cap = _ti_find_extra(rtic, &rtic->extras, "use");
			if (cap == NULL)
				dowarn("%s: use no longer exists - impossible",
					rtic->name);
			else {
				char *scap = (char *)cap -
				    (4 + sizeof(uint16_t));
				cap++;
				num = _ti_decode_16(&cap);
				cap += num;
				memn = rtic->extras.bufpos -
				    (cap - rtic->extras.buf);
				memmove(scap, cap, memn);
				rtic->extras.bufpos -= cap - scap;
				cap = scap;
				rtic->extras.entries--;
				merged++;
			}
		}
		free(basename);
	}

	if (merged == 0 && skipped != 0)
		dowarn("circular use detected");
	return merged;
}

static int
print_dump(int argc, char **argv)
{
	TERM *term;
	uint8_t *buf;
	int i, n;
	size_t j, col;
	ssize_t len;

	printf("struct compiled_term {\n");
	printf("\tconst char *name;\n");
	printf("\tconst char *cap;\n");
	printf("\tsize_t caplen;\n");
	printf("};\n\n");

	printf("const struct compiled_term compiled_terms[] = {\n");

	n = 0;
	for (i = 0; i < argc; i++) {
		term = find_newest_term(argv[i]);
		if (term == NULL) {
			warnx("%s: no description for terminal", argv[i]);
			continue;
		}
		if (term->base_term != NULL) {
			warnx("%s: cannot dump alias", argv[i]);
			continue;
		}
		/* Don't compile the aliases in, save space */
		free(term->tic->alias);
		term->tic->alias = NULL;
		len = _ti_flatten(&buf, term->tic);
		if (len == 0 || len == -1)
			continue;

		printf("\t{\n");
		printf("\t\t\"%s\",\n", argv[i]);
		n++;
		for (j = 0, col = 0; j < (size_t)len; j++) {
			if (col == 0) {
				printf("\t\t\"");
				col = 16;
			}

			col += printf("\\%03o", (uint8_t)buf[j]);
			if (col > 75) {
				printf("\"%s\n",
				    j + 1 == (size_t)len ? "," : "");
				col = 0;
			}
		}
		if (col != 0)
			printf("\",\n");
		printf("\t\t%zu\n", len);
		printf("\t}");
		if (i + 1 < argc)
			printf(",");
		printf("\n");
		free(buf);
	}
	printf("};\n");

	return n;
}

static void
write_database(const char *dbname, int argc, char **argv)
{
	struct cdbw *db;
	char *tmp_dbname;
	TERM *term;
	int fd, i;

	db = cdbw_open();
	if (db == NULL)
		err(EXIT_FAILURE, "cdbw_open failed");
	/* Save the terms */
	if (argc > 0) {
		for (i = 0; i < argc; i++) {
			term = find_newest_term(argv[i]);
			if (term == NULL) {
				warnx("%s: no description for terminal",
				    argv[i]);
				continue;
			}
			save_term(db, term);
		}
	} else {
		STAILQ_FOREACH(term, &terms, next)
			save_term(db, term);
	}

	tmp_dbname = malloc(strlen(dbname) + 8);
	if (!tmp_dbname)
		err(EXIT_FAILURE, NULL);
	sprintf(tmp_dbname, "%s.XXXXXX", dbname);
	fd = mkstemp(tmp_dbname);
	if (fd == -1)
		err(EXIT_FAILURE,
		    "creating temporary database %s failed", tmp_dbname);
	if (cdbw_output(db, fd, "NetBSD terminfo", cdbw_stable_seeder))
		err(EXIT_FAILURE,
		    "writing temporary database %s failed", tmp_dbname);
	if (fchmod(fd, 0666))
		err(EXIT_FAILURE, "fchmod failed");
	if (close(fd))
		err(EXIT_FAILURE,
		    "writing temporary database %s failed", tmp_dbname);
	if (rename(tmp_dbname, dbname))
		err(EXIT_FAILURE, "renaming %s to %s failed", tmp_dbname, dbname);
	free(tmp_dbname);
	cdbw_close(db);
}

int
main(int argc, char **argv)
{
	int ch, cflag, sflag, flags;
	char *source, *dbname, *buf, *ofile;
	FILE *f;
	size_t buflen;
	ssize_t len;
	TBUF tbuf;
	struct term *term;

	cflag = sflag = 0;
	ofile = NULL;
	flags = TIC_ALIAS | TIC_DESCRIPTION | TIC_WARNING;
	while ((ch = getopt(argc, argv, "Saco:sx")) != -1)
	    switch (ch) {
	    case 'S':
		    Sflag = 1;
		    /* We still compile aliases so that use= works.
		     * However, it's removed before we flatten to save space. */
		    flags &= ~TIC_DESCRIPTION;
		    break;
	    case 'a':
		    flags |= TIC_COMMENT;
		    break;
	    case 'c':
		    cflag = 1;
		    break;
	    case 'o':
		    ofile = optarg;
		    break;
	    case 's':
		    sflag = 1;
		    break;
	    case 'x':
		    flags |= TIC_EXTRA;
		    break;
	    case '?': /* FALLTHROUGH */
	    default:
		    fprintf(stderr, "usage: %s [-acSsx] [-o file] source\n",
			argv[0] ? argv[0] : "tic");
		    return EXIT_FAILURE;
	    }

	if (optind == argc)
		errx(1, "No source file given");
	source = argv[optind++];
	f = fopen(source, "r");
	if (f == NULL)
		err(EXIT_FAILURE, "fopen: %s", source);

	hcreate(HASH_SIZE);

	buf = tbuf.buf = NULL;
	buflen = tbuf.buflen = tbuf.bufpos = 0;
	while ((len = getline(&buf, &buflen, f)) != -1) {
		/* Skip comments */
		if (*buf == '#')
			continue;
		if (buf[len - 1] != '\n') {
			process_entry(&tbuf, flags);
			dowarn("last line is not a comment"
			    " and does not end with a newline");
			continue;
		}
		/*
		 * If the first char is space not a space then we have a
		 * new entry, so process it.
		 */
		if (!isspace((unsigned char)*buf) && tbuf.bufpos != 0)
			process_entry(&tbuf, flags);

		/* Grow the buffer if needed */
		grow_tbuf(&tbuf, len);
		/* Append the string */
		memcpy(tbuf.buf + tbuf.bufpos, buf, len);
		tbuf.bufpos += len;
	}
	free(buf);
	/* Process the last entry if not done already */
	process_entry(&tbuf, flags);
	free(tbuf.buf);

	/* Merge use entries until we have merged all we can */
	while (merge_use(flags) != 0)
		;

	if (Sflag) {
		if (ofile && !freopen(ofile, "w", stdout))
			err(EXIT_FAILURE, "open %s", ofile);
		print_dump(argc - optind, argv + optind);
		return error_exit;
	}

	if (cflag)
		return error_exit;

	if (ofile == NULL) {
		dbname = malloc(strlen(source) + 5);
		if (!dbname)
			err(EXIT_FAILURE, "malloc");
		sprintf(dbname, "%s.cdb", source);
	} else {
		dbname = ofile;
	}
	write_database(dbname, argc - optind, argv + optind);

	if (sflag != 0)
		fprintf(stderr, "%zu entries and %zu aliases written to %s\n",
		    nterm, nalias, dbname);

	if (ofile == NULL)
		free(dbname);
	while ((term = STAILQ_FIRST(&terms)) != NULL) {
		STAILQ_REMOVE_HEAD(&terms, next);
		_ti_freetic(term->tic);
		free(term->name);
		free(term);
	}

	return EXIT_SUCCESS;
}


code:
/*
Decompress font file
intended for testing only.

usage: ttfdz infile outfile

misc 2025, Public Domain
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

*/

#include <stdio.h>
#include <stdlib.h>

#define SINFL_IMPLEMENTATION
#include "sinfl.h"

int main( int argc, char **argv ){
	if ( argc!=3 ){
		fprintf(stderr,"Usage: ttfdz infile outfile\n");
		exit(22);
	}

	void *in,*out;

	FILE* fp = fopen(argv[1], "r");
	if (!fp) exit(2);
	fseek(fp, 0, SEEK_END);
	size_t size = (size_t)ftell(fp);
	fseek(fp, 0, SEEK_SET);
	in = calloc(size, 1);
	fread(in, 1, (size_t)size, fp);
	fclose(fp);

	out = calloc( size*8,1 ); // well. should work, for ttf fonts.
	// This is for testing only, so.

   size_t len = sinflate( out, size*8, in, size );
	if ( len == size*8 ){
		fprintf( stderr, "buffer too small, internal error\n" );
		exit(1);
	}

	//printf("len: %d\n",len);

	fp = fopen( argv[2], "r" );
	if ( fp ){
		fprintf( stderr, "outfile exists: %s\nAbort\n",argv[2] );
		fclose(fp);
		exit(1);
	}

	fp = fopen( argv[2], "w" );

	if (!fp){
		fprintf(stderr, "Cannot write to %s\n", argv[2] );
		exit(1);
	}
	fwrite( out, 1, len, fp );
	fclose(fp);

	printf("Decompress:\n%s -> %s\n%d -> %d\n", argv[1], argv[2], size, len );

	return(0);
}


code:
/*
Compress font files (or other files)
Error checking should be done separately,
intended only for the build process of slterm.

Limits: no error checking, will not work very well with bigger files,
 there might be more trouble.
 Works for the intended usage, however.

usage: ttfz infile outfile

misc 2025, Public Domain
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

*/

#include <stdio.h>
#include <stdlib.h>

#define SDEFL_IMPLEMENTATION
#include "sdefl.h"

static struct sdefl sdefl;

int main( int argc, char **argv ){
	if ( argc!=3 ){
		fprintf(stderr,"Usage: ttfz infile outfile\n");
		exit(22);
	}

	void *in,*out;

	FILE* fp = fopen(argv[1], "r");
	if (!fp) exit(2);
	fseek(fp, 0, SEEK_END);
	size_t size = (size_t)ftell(fp);
	fseek(fp, 0, SEEK_SET);
	in = calloc(size, 1);
	fread(in, 1, (size_t)size, fp);
	fclose(fp);

	out = calloc( size*2,1 );

   size_t len = sdeflate(&sdefl, out, in, (int)size, 7);

	//printf("len: %d\n",len);

	fp = fopen( argv[2], "r" );
	if ( fp ){
		fprintf( stderr, "outfile exists: %s\nAbort\n",argv[2] );
		fclose(fp);
		exit(1);
	}

	fp = fopen( argv[2], "w" );

	if (!fp){
		fprintf(stderr, "Cannot write to %s\n", argv[2] );
		exit(1);
	}
	fwrite( out, 1, len, fp );
	fclose(fp);

	printf("Compress:\n%s -> %s\n%d -> %d\n", argv[1], argv[2], size, len );

	return(0);
}


code:
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto

###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs     diff=csharp

###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln       merge=binary
#*.csproj    merge=binary
#*.vbproj    merge=binary
#*.vcxproj   merge=binary
#*.vcproj    merge=binary
#*.dbproj    merge=binary
#*.fsproj    merge=binary
#*.lsproj    merge=binary
#*.wixproj   merge=binary
#*.modelproj merge=binary
#*.sqlproj   merge=binary
#*.wwaproj   merge=binary

###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg   binary
#*.png   binary
#*.gif   binary

###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc   diff=astextplain
#*.DOC   diff=astextplain
#*.docx  diff=astextplain
#*.DOCX  diff=astextplain
#*.dot   diff=astextplain
#*.DOT   diff=astextplain
#*.pdf   diff=astextplain
#*.PDF   diff=astextplain
#*.rtf   diff=astextplain
#*.RTF   diff=astextplain

repo_name: Valianteffort/rimworld

path: .gitattributes

license: unknown


code:
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore

# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates

# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/

# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/

# Visual Studio 2017 auto generated files
Generated\ Files/

# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*

# NUNIT
*.VisualState.xml
TestResult.xml

# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c

# Benchmark Results
BenchmarkDotNet.Artifacts/

# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/

# StyleCop
StyleCopReport.xml

# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc

# Chutzpah Test files
_Chutzpah*

# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb

# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap

# Visual Studio Trace Files
*.e2e

# TFS 2012 Local Workspace
$tf/

# Guidance Automation Toolkit
*.gpState

# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user

# JustCode is a .NET coding add-in
.JustCode

# TeamCity is a build add-in
_TeamCity*

# DotCover is a Code Coverage Tool
*.dotCover

# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json

# Visual Studio code coverage results
*.coverage
*.coveragexml

# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*

# MightyMoose
*.mm.*
AutoTest.Net/

# Web workbench (sass)
.sass-cache/

# Installshield output folder
[Ee]xpress/

# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html

# Click-Once directory
publish/

# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj

# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/

# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets

# Microsoft Azure Build Output
csx/
*.build.csdef

# Microsoft Azure Emulator
ecf/
rcf/

# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx

# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/

# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs

# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk

# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/

# RIA/Silverlight projects
Generated_Code/

# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak

# SQL Server files
*.mdf
*.ldf
*.ndf

# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- Backup*.rdl

# Microsoft Fakes
FakesAssemblies/

# GhostDoc plugin setting file
*.GhostDoc.xml

# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/

# Visual Studio 6 build log
*.plg

# Visual Studio 6 workspace options file
*.opt

# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw

# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions

# Paket dependency manager
.paket/paket.exe
paket-files/

# FAKE - F# Make
.fake/

# JetBrains Rider
.idea/
*.sln.iml

# CodeRush personal settings
.cr/personal

# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc

# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config

# Tabs Studio
*.tss

# Telerik's JustMock configuration file
*.jmconfig

# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs

# OpenCover UI analysis results
OpenCover/

# Azure Stream Analytics local run output
ASALocalRun/

# MSBuild Binary and Structured Log
*.binlog

# NVidia Nsight GPU debugger configuration file
*.nvuser

# MFractors (Xamarin productivity tool) working folder
.mfractor/

# Local History for Visual Studio
.localhistory/

# BeatPulse healthcheck temp database
healthchecksdb
/Source/Patches/PawnAnimationPatches/HarmonyPatch_Pawn_DrawTracker.cs
/Source/Patches/PawnAnimationPatches/HarmonyPatch_PawnRotation.cs
/Source/Patches/PawnAnimationPatches/HarmonyPatch_PawnRenderer.cs
/Source/Patches/OtherModPatches/HarmonyPatch_ShowHairWithHats.cs
/Source/Patches/OtherModPatches/HarmonyPatch_FacialAnimation.cs
/Source/Patches/OtherModPatches/HarmonyPatch_DontShaveYourHead.cs
/Source/Patches/OtherModPatches/HarmonyPatch_CSL.cs
/Source/Patches/OtherModPatches/HarmonyPatch_AlienRace.cs
/Source/Patches/ThingAnimationPatches/HarmonyPatch_ThingDrawAt.cs
/Defs/AnimationDefs/Animations_SexToys.xml

path: .gitignore