function left(y, r, need_term, y0)
{
	if (need_term)
		sym_term(SYM, 0, y * pin_grid, "left", prefix "1")

	if (y0 != "")
		sym_line(SYM, 0, y * pin_grid, 0, y0 * pin_grid)

	sym_line(SYM, 0, y * pin_grid, 0.3 * pin_grid, y * pin_grid)
	if (P["style"] ~ "push")
		sym_arc(SYM, (0.3 + r) * pin_grid, y * pin_grid, r * pin_grid, 0, 360)
}

function right(x0, y0, prefix, r, t, left_multi,   RES    ,tune,nn,n,tn,i)
{
	tn = 2
	if ((t % 2) == 0)
		tune = 1
	i = 0
	for(nn = -int(t/2); nn < int(t/2+0.5); nn++) {
		n = nn + tune;
		RES[i, "y"] = y0+n
		RES[i, "x"] = x0-0.3 - r
		sym_term(SYM, x0 * pin_grid, (y0+n) * pin_grid, "right", prefix tn)
		sym_line(SYM, (x0-0.3) * pin_grid, (y0+n) * pin_grid, x0 * pin_grid, (y0 + n) * pin_grid)
		if (r > 0)
		sym_arc(SYM, (x0-0.3 - r) * pin_grid, (y0+n) * pin_grid, r * pin_grid, 0, 360)
		if (left_multi)
			left(y0+n, r, 0, y0)

		tn++
		i++
	}

	return n
}

function gen_straight(y0, prefix, last     ,n,t,tn,yoffs,r,nn,tune,cap,coupler,relay,left_multi)
{
	r = 0.1
	if (P["style"] == "invpush")
		yoffs = -r;
	else
		yoffs = r;

	t = P["throw"]

	if ((P["style"] == "push") || (P["style"] == "invpush"))
		left_multi = 1

# generate left side
	left(y0, r, 1)

# generate right side terminals
	n = right(2, y0, prefix, r, t, left_multi)

# generate switch mechanics
	if (P["style"] == "switch") {
		sym_line(SYM, 0.3*pin_grid, y0 * pin_grid, 1.4*pin_grid, (y0+0.8) * pin_grid)
		coupler = y0+0.5
	}
	else if (P["style"] == "relay") {
		sym_line(SYM, 0.3*pin_grid, y0 * pin_grid, 1.4*pin_grid, (y0+0.8) * pin_grid)
		coupler = y0+0.5
		relay = 1.5
	}
	else if (P["style"] == "push") {
		sym_line(SYM, 0.3*pin_grid, (y0+1-r) * pin_grid, 1.7*pin_grid, (y0+1-r) * pin_grid)
		coupler = y0+1-r
		cap = 2
	}
	else if (P["style"] == "invpush") {
		sym_line(SYM, 0.3*pin_grid, (y0-r) * pin_grid, 1.7*pin_grid, (y0-r) * pin_grid)
		coupler = y0-r
		cap = 1
	}
	else
		error("invalid switch style " P["style"])

	COUPLER["top"] = y0 + n
	if (cap || relay)
		COUPLER["top"] += cap + relay
	else
		COUPLER["top"] -= 0.5

	if (COUPLER["bottom"] == "")
		COUPLER["bottom"] = coupler

# generate cap or relay
	if (last) {
		if (cap) {
			sym_line(SYM, 0.4*pin_grid, COUPLER["top"] * pin_grid, 1.6*pin_grid, COUPLER["top"] * pin_grid)
			sym_line(SYM, 0.4*pin_grid, COUPLER["top"] * pin_grid, 0.4*pin_grid, (COUPLER["top"]-r*2) * pin_grid)
			sym_line(SYM, 1.6*pin_grid, COUPLER["top"] * pin_grid, 1.6*pin_grid, (COUPLER["top"]-r*2) * pin_grid)
		}
		if (relay) {
			sym_rect(SYM, 0*pin_grid, (COUPLER["top"]+3) * pin_grid, 2*pin_grid, COUPLER["top"] * pin_grid)
			sym_line(SYM, 0*pin_grid, (COUPLER["top"]+0.5) * pin_grid, 2*pin_grid, (COUPLER["top"]+2.5) * pin_grid)
			sym_term(SYM, 0, (COUPLER["top"]+1.5) * pin_grid, "left", "coil1")
			sym_term(SYM, 2*pin_grid, (COUPLER["top"]+1.5) * pin_grid, "right", "coil2")
		}
	}

	return t+1
}

function gen_rotary(y0, prefix, last     ,RES,n,t,da,sa,a,rx0,ry0,rx,ry,rr,r)
{
	r = 0.1
	rr = 1
	t = P["throw"]
	sa = 3.141592654/4
	if ((t%2) == 1)
		da = (sa*2)/(t-1)
	else {
		da = (sa*2)/t
		sa -= da
	}

# generate left side
	left(y0, r, 1)

# generate right side terminals
	right(4, y0, prefix, 0, t, 0, RES)

	rx0 = 1
	ry0 = y0
	a = -sa
	for(n = 0; n < t; n++) {
		rx = rx0 + cos(a) * rr
		ry = ry0 + sin(a) * rr
		sym_line(SYM, int(rx * pin_grid), int(ry * pin_grid), RES[n, "x"] * pin_grid, RES[n, "y"] * pin_grid)
		a += da
	}

	sym_line(SYM, 0.3*pin_grid, y0 * pin_grid, 1.8*pin_grid, (y0+0.3) * pin_grid)
	coupler = y0+0.15

	COUPLER["top"] = y0+0.15
	if (COUPLER["bottom"] == "")
		COUPLER["bottom"] = coupler

	return t+1
}


function gen_sect(y0, prefix, last)
{
	if (P["style"] == "rotary") return gen_rotary(y0, prefix, last)
	return gen_straight(y0, prefix, last)
}

BEGIN {
	help_auto()

	set_arg(P, "?pole", "1")
	set_arg(P, "?throw", "1")
	set_arg(P, "?style", "switch")

	proc_args(P, "pole, throw, style")

	P["pole"] = int(P["pole"])
	P["throw"] = int(P["throw"])

	if (P["pole"] > 26)
		error("Too many poles; must be less than 27");
	if (P["pole"] < 1)
		error("Too few poles; must be at least 1");
	if (P["throw"] < 1)
		error("Too few throws; must be at least 1");

	sym_begin("SW??", -pin_grid*2, -pin_grid)
	grp_attr_append(SYM, "spice/omit", "yes")

	prefix=""
	y0 = 0
	for(pole = 0; pole < P["pole"]; pole++) {
		if (P["pole"] > 1)
			prefix = sprintf("%c", 65+pole)
		y0 += gen_sect(y0, prefix, (pole == P["pole"]-1))
	}

# draw coupler
	if (COUPLER["bottom"] != COUPLER["top"])
		sym_line(SYM, 1*pin_grid, COUPLER["bottom"] * pin_grid, 1*pin_grid, COUPLER["top"] * pin_grid)


	sym_end()
}
