#
#  Makefile - v620emu, a Varian 620/L emulator
#
# Copyright (c) 2026 Large Scale Systems Museum
# By Dave McGuire <mcguire@lssmuseum.org>
#
#
# Targets:
#   all (default)  build the emulator, src/v620emu, and its man page,
#                  docs/v620emu.1 (from docs/v620emu.1.in, with the version
#                  number filled in from src/version.h)
#   examples       assemble the example tapes (examples/*.ptp) from their
#                  DAS sources (requires v620asm, a companion project, on
#                  $PATH; the tapes aren't stored in the repository)
#   test           build, then run the test suite in tests/
#   install        install the emulator into $(PREFIX)/bin, its man page
#                  into $(PREFIX)/share/man/man1, and its manual, license,
#                  and sample config into $(PREFIX)/share/doc/<progname>;
#                  PREFIX defaults to /usr/local, and DESTDIR is honored
#                  for staged installs
#   clangd         build under bear to generate compile_commands.json
#   dist           create <progname>-<version>.tar.bz2, with the name and
#                  version taken from src/version.h, containing
#                  everything needed to build, test, and use the
#                  emulator (and nothing from Subversion)
#   clean          remove everything the other targets build
#

CC = cc
CFLAGS = -Wall -Wextra -std=c99 -O2 -D_POSIX_C_SOURCE=200809L -D_DEFAULT_SOURCE
LDFLAGS =
LDLIBS = -lncursesw

# MacOS X hides everything beyond strict POSIX (INADDR_LOOPBACK,
# TCP_NODELAY, ...) when _POSIX_C_SOURCE is defined, unless
# _DARWIN_C_SOURCE is also defined. Its system ncurses is already the
# wide-character build, and is named plain libncurses.
ifeq ($(shell uname -s),Darwin)
CFLAGS += -D_DARWIN_C_SOURCE
LDLIBS = -lncurses
endif
V620ASM = v620asm
PYTHON = python3
INSTALL = install

PREFIX = /usr/local
BINDIR = $(PREFIX)/bin
MANDIR = $(PREFIX)/share/man/man1
DOCINSTDIR = $(PREFIX)/share/doc/$(PROGNAME)

SRCDIR = src
EXDIR = examples
TESTDIR = tests
DOCDIR = docs

PROGNAME := $(shell sed -n 's/.*PROGNAME[ \t]*"\(.*\)".*/\1/p' $(SRCDIR)/version.h)
VERSION  := $(shell sed -n 's/.*VERSION[ \t]*"\(.*\)".*/\1/p' $(SRCDIR)/version.h)
DISTDIR  = $(PROGNAME)-$(VERSION)

PROG = $(SRCDIR)/v620emu
SRCS = $(SRCDIR)/v620core.c $(SRCDIR)/v620tape.c $(SRCDIR)/v620tty.c \
       $(SRCDIR)/v620ptape.c $(SRCDIR)/v620pim.c $(SRCDIR)/v620rtc.c \
       $(SRCDIR)/v620mt.c $(SRCDIR)/v620mtimage.c $(SRCDIR)/v620dio.c \
       $(SRCDIR)/v620bic.c \
       $(SRCDIR)/v620disc.c \
       $(SRCDIR)/v620cr.c \
       $(SRCDIR)/v620uasc.c \
       $(SRCDIR)/v620common.c $(SRCDIR)/v620cli.c \
       $(SRCDIR)/v620panel.c $(SRCDIR)/main.c
HDRS = $(SRCDIR)/v620core.h $(SRCDIR)/v620tape.h $(SRCDIR)/v620tty.h \
       $(SRCDIR)/v620ptape.h $(SRCDIR)/v620pim.h $(SRCDIR)/v620rtc.h \
       $(SRCDIR)/v620mt.h $(SRCDIR)/v620mtimage.h $(SRCDIR)/v620dio.h \
       $(SRCDIR)/v620bic.h \
       $(SRCDIR)/v620disc.h \
       $(SRCDIR)/v620cr.h \
       $(SRCDIR)/v620uasc.h \
       $(SRCDIR)/v620ui.h $(SRCDIR)/version.h
OBJS = $(SRCS:.c=.o)
MANPAGE = $(DOCDIR)/$(PROGNAME).1

# Everything that goes into the distribution, beyond $(SRCS) and $(HDRS).
# These are explicit lists rather than wildcards so that editor backups,
# build products, and local scratch files can't end up in a release.
DOCS = README.md
DOC_FILES = $(DOCDIR)/MANUAL.md $(DOCDIR)/LICENSE.md $(DOCDIR)/v620.cfg-sample
EXAMPLES = teletype_hello teletype_echo clock
TAPES = $(EXAMPLES:%=$(EXDIR)/%.ptp)
EXAMPLE_FILES = $(EXAMPLES:%=$(EXDIR)/%.das) $(EXAMPLES:%=$(EXDIR)/%.cfg)
TEST_FILES = $(TESTDIR)/README.md $(TESTDIR)/v620_harness.py \
             $(TESTDIR)/test_instructions.py $(TESTDIR)/test_tapes.py \
             $(TESTDIR)/test_teletype.py $(TESTDIR)/test_panel.py \
             $(TESTDIR)/test_interrupts.py $(TESTDIR)/test_examples.py \
             $(TESTDIR)/test_maintain.py $(TESTDIR)/test_magtape.py \
             $(TESTDIR)/test_dio.py $(TESTDIR)/test_ptape.py
TEST_DATA_FILES = $(TESTDIR)/data/bld2.oct
MAINTAIN = mainii prelim inspt1 inspt2 mempt1 mempt2 tytest pwrfai pimtst \
           rtctst mttest
MAINTAIN_FILES = $(MAINTAIN:%=$(TESTDIR)/data/maintain2/%.oct)

all: $(PROG) $(MANPAGE)

$(PROG): $(OBJS)
	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS)

$(MANPAGE): $(MANPAGE).in $(SRCDIR)/version.h
	sed 's/@VERSION@/$(VERSION)/g' $(MANPAGE).in > $@

$(SRCDIR)/%.o: $(SRCDIR)/%.c
	$(CC) $(CFLAGS) -c $< -o $@

$(OBJS): $(HDRS)

examples: $(TAPES)

$(EXDIR)/%.ptp: $(EXDIR)/%.das
	cd $(EXDIR) && $(V620ASM) $*.das

test: all
	cd $(TESTDIR) && $(PYTHON) -m unittest discover -s . -p "test_*.py" -v

install: all
	$(INSTALL) -d $(DESTDIR)$(BINDIR) $(DESTDIR)$(MANDIR) $(DESTDIR)$(DOCINSTDIR)
	$(INSTALL) -m 755 $(PROG) $(DESTDIR)$(BINDIR)
	$(INSTALL) -m 644 $(MANPAGE) $(DESTDIR)$(MANDIR)
	$(INSTALL) -m 644 $(DOC_FILES) $(DESTDIR)$(DOCINSTDIR)

clangd:
	bear -- make

dist:
	@rm -rf $(DISTDIR)
	@rm -f $(DISTDIR).tar.bz2
	@mkdir -p $(DISTDIR)/$(SRCDIR) $(DISTDIR)/$(EXDIR) $(DISTDIR)/$(TESTDIR) \
		$(DISTDIR)/$(TESTDIR)/data/maintain2 $(DISTDIR)/$(DOCDIR)
	@cp Makefile $(DOCS) $(DISTDIR)
	@cp $(SRCS) $(HDRS) $(DISTDIR)/$(SRCDIR)
	@cp $(EXAMPLE_FILES) $(DISTDIR)/$(EXDIR)
	@cp $(TEST_FILES) $(DISTDIR)/$(TESTDIR)
	@cp $(TEST_DATA_FILES) $(DISTDIR)/$(TESTDIR)/data
	@cp $(MAINTAIN_FILES) $(DISTDIR)/$(TESTDIR)/data/maintain2
	@cp $(DOC_FILES) $(MANPAGE).in $(DISTDIR)/$(DOCDIR)
	@tar -cjf $(DISTDIR).tar.bz2 $(DISTDIR)
	@rm -rf $(DISTDIR)
	@echo Distribution file $(DISTDIR).tar.bz2 created.

clean:
	rm -f $(PROG) $(OBJS) $(MANPAGE) $(TAPES) $(EXDIR)/*.lst
	rm -rf $(TESTDIR)/__pycache__

.PHONY: all examples test install clangd dist clean
