Clean some boot text and shutdown code path fixes

This commit is contained in:
Willem Cazander 2025-07-15 17:39:41 +02:00
parent 54d9e98254
commit 614bf64a8d
6 changed files with 90 additions and 69 deletions

View file

@ -60,6 +60,7 @@ public enum GDXAppTos4 implements BãßᛗᚢᛗᛗᛉVū́ǘrChaliceEnumShot
private Framework systemBundle; private Framework systemBundle;
private GDXAppTos4Activator systemActivator; private GDXAppTos4Activator systemActivator;
private Map<Class<? extends Screen>,Screen> screens; private Map<Class<? extends Screen>,Screen> screens;
volatile private boolean running = true;
@BãßBȍőnSpiderWire注(paint = Vū́ǘrBȍőnSupportꞱᴿᴳᴮ.ẞassPaint.ꞱBurnWireFly.class) @BãßBȍőnSpiderWire注(paint = Vū́ǘrBȍőnSupportꞱᴿᴳᴮ.ẞassPaint.ꞱBurnWireFly.class)
@BãßBȍőnSpiderWireFly注(eye = "selectScreenCounter") @BãßBȍőnSpiderWireFly注(eye = "selectScreenCounter")
@ -80,6 +81,10 @@ public enum GDXAppTos4 implements BãßᛗᚢᛗᛗᛉVū́ǘrChaliceEnumShot
systemActivator.BãßInit(args, viewWidth, viewHeight, fileChooser, this); systemActivator.BãßInit(args, viewWidth, viewHeight, fileChooser, this);
} }
public boolean isRunning() {
return running;
}
@Override @Override
public void create() { public void create() {
systemBundle = GDXAppTos4Startup.init(this, systemActivator); systemBundle = GDXAppTos4Startup.init(this, systemActivator);
@ -116,6 +121,7 @@ public enum GDXAppTos4 implements BãßᛗᚢᛗᛗᛉVū́ǘrChaliceEnumShot
@Override @Override
public void dispose() { public void dispose() {
this.running = false;
this.screen = null; this.screen = null;
for (Screen screen:screens.values()) { for (Screen screen:screens.values()) {
screen.dispose(); screen.dispose();
@ -130,6 +136,22 @@ public enum GDXAppTos4 implements BãßᛗᚢᛗᛗᛉVū́ǘrChaliceEnumShot
} catch (InterruptedException ignored) { } catch (InterruptedException ignored) {
} }
Gdx.app.log(this.getClass().getSimpleName(), "Screens disposed and system stopped."); Gdx.app.log(this.getClass().getSimpleName(), "Screens disposed and system stopped.");
// TODO: check why thread like FelixResolver-* and logback don't get stopped...
// the JVM does exit after ~30 sec, but with a manual exit request it is faster...
System.exit(0); // remove this exit(0) invoke, now the test-run shutdown is not nice
// see output without the above manual exit(0);
//[WARNING] thread Thread[logback-1,5,love.distributedrebirth.gdxapp4d.boot.desktop.GDXAppDesktopLauncher] was interrupted but is still alive after waiting at least 14999msecs
//[WARNING] thread Thread[logback-1,5,love.distributedrebirth.gdxapp4d.boot.desktop.GDXAppDesktopLauncher] will linger despite being asked to die via interruption
//[WARNING] thread Thread[FelixResolver-1,5,love.distributedrebirth.gdxapp4d.boot.desktop.GDXAppDesktopLauncher] will linger despite being asked to die via interruption
//[WARNING] thread Thread[FelixResolver-2,5,love.distributedrebirth.gdxapp4d.boot.desktop.GDXAppDesktopLauncher] will linger despite being asked to die via interruption
//[WARNING] thread Thread[FelixResolver-3,5,love.distributedrebirth.gdxapp4d.boot.desktop.GDXAppDesktopLauncher] will linger despite being asked to die via interruption
//[WARNING] thread Thread[FelixResolver-4,5,love.distributedrebirth.gdxapp4d.boot.desktop.GDXAppDesktopLauncher] will linger despite being asked to die via interruption
//[WARNING] thread Thread[FelixResolver-5,5,love.distributedrebirth.gdxapp4d.boot.desktop.GDXAppDesktopLauncher] will linger despite being asked to die via interruption
//[WARNING] thread Thread[FelixResolver-6,5,love.distributedrebirth.gdxapp4d.boot.desktop.GDXAppDesktopLauncher] will linger despite being asked to die via interruption
//[WARNING] thread Thread[FelixResolver-7,5,love.distributedrebirth.gdxapp4d.boot.desktop.GDXAppDesktopLauncher] will linger despite being asked to die via interruption
//[WARNING] thread Thread[FelixResolver-8,5,love.distributedrebirth.gdxapp4d.boot.desktop.GDXAppDesktopLauncher] will linger despite being asked to die via interruption
//[WARNING] NOTE: 9 thread(s) did not finish despite being asked to via interruption. This is not a problem with exec:java, it is a problem with the running code. Although not serious, it should be remedied.
//[WARNING] Couldn't destroy threadgroup org.codehaus.mojo.exec.ExecJavaMojo$IsolatedThreadGroup[name=love.distributedrebirth.gdxapp4d.boot.desktop.GDXAppDesktopLauncher,maxpri=10]
} }
@Override @Override

View file

@ -46,6 +46,7 @@ import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException; import org.osgi.framework.BundleException;
import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.x4o.xml.io.X4OConnectionException; import org.x4o.xml.io.X4OConnectionException;
@ -132,45 +133,47 @@ public class GDXAppTos4Activator implements BundleActivator {
gdxFont.dispose(); gdxFont.dispose();
} }
private void startError(String msg) {
bootScreen.bootLineError("ERROR: " + msg);
startError = true;
LOG.error(msg);
}
@Override @Override
public void start(final BundleContext context) { public void start(final BundleContext context) {
bootScreen.bootLine("Mecca System eXtension superscript Four"); bootScreen.bootLine("Mecca System eXtension superscript Four");
bootScreen.bootLine("tos4: starting..."); bootScreen.bootLine("nx01: starting Temple OS engine");
bootScreen.bootLine("init-cpus: "+Runtime.getRuntime().availableProcessors()); bootScreen.bootLine("init-cpus: "+Runtime.getRuntime().availableProcessors());
bootScreen.bootLine("free-memory: 0x"+Long.toHexString(Runtime.getRuntime().freeMemory())); bootScreen.bootLine("free-memory: 0x"+Long.toHexString(Runtime.getRuntime().freeMemory()));
BãßBȍőnBőatWindKnots harbor = Bãß.أَكْبَرײꣻײالله.harborᴮʳᵉᵉᶻᵉ(BãßBȍőnBőatWind.SAILOR_MOON_SKIRT_DUSTER); BãßBȍőnBőatWindKnots harbor = Bãß.أَكْبَرײꣻײالله.harborᴮʳᵉᵉᶻᵉ(BãßBȍőnBőatWind.SAILOR_MOON_SKIRT_DUSTER);
bootScreen.bootLine("harbor: solar-winds="+harbor.getSolarWinds().size()+" storm-troopers="+harbor.getStormTroopers()); bootScreen.bootLine("nx01-harbor: solar-winds="+harbor.getSolarWinds().size()+" storm-troopers="+harbor.getStormTroopers());
boolean useLocal = args.contains("use-local"); boolean useLocal = args.contains("use-local");
warpshipHome = new File(WARPSHIP_HOME); warpshipHome = new File(WARPSHIP_HOME);
if (!warpshipHome.exists()) { if (!warpshipHome.exists()) {
bootScreen.bootLineError("ERROR: No Warpship home."); startError("No Warpship home.");
startError = true;
return; return;
} }
hyperdriveHome = new File(warpshipHome, HYPERDRIVE_HOME); hyperdriveHome = new File(warpshipHome, HYPERDRIVE_HOME);
if (!hyperdriveHome.exists()) { if (!hyperdriveHome.exists()) {
bootScreen.bootLineError("ERROR: No Hyperdrive home."); startError("No Hyperdrive home.");
startError = true;
return; return;
} }
File warpShip = new File(warpshipHome, Warpᵐᵉ.WARP_SHIP); File warpShip = new File(warpshipHome, Warpᵐᵉ.WARP_SHIP);
bootScreen.bootLine("warp-ship: "+warpShip); bootScreen.bootLine("warp-ship: "+warpShip);
if (!warpShip.exists()) { if (!warpShip.exists()) {
bootScreen.bootLineError("ERROR: No warp-ship.xml found."); startError("No warp-ship.xml found.");
startError = true;
return; return;
} }
try { try {
warpshipDevice = WaterDeviceDriver.newInstance().createReader().readFile(warpShip); warpshipDevice = WaterDeviceDriver.newInstance().createReader().readFile(warpShip);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); LOG.error(e.getMessage(), e);
bootScreen.bootLineError("ERROR: "+e.getMessage()); startError(e.getMessage());
startError = true;
return; return;
} }
bootScreen.bootLine("warp-engine: "+warpshipDevice.theShip().getName()); bootScreen.bootLine("warp-engine: "+warpshipDevice.theShip().getName());
@ -209,17 +212,18 @@ public class GDXAppTos4Activator implements BundleActivator {
try { try {
result = systemWarpShip.loadWaterOcean(context, registratedSeas, warpshipDevice.theShip().getEngine(), v -> bootScreen.bootLine(v)); result = systemWarpShip.loadWaterOcean(context, registratedSeas, warpshipDevice.theShip().getEngine(), v -> bootScreen.bootLine(v));
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); if (!GDXAppTos4.INSTANCE.isRunning()) {
bootScreen.bootLineError("ERROR: "+e.getMessage()); return;
startError = true; }
LOG.error(e.getMessage(), e);
startError(e.getMessage());
return; return;
} }
if (result > 0) { if (result < 0) {
bootScreen.bootLineError("tos4: FAILURE BOOT ABORTED"); startError("SPACE DOCK FAILURE, ENGINE BOOT ABORTED");
startError = true;
return; return;
} }
bootScreen.bootLine("tos4: chains resolved."); bootScreen.bootLine("nx01-space: Docked with " + result + " warp oceans");
List<File> fonts = systemWarpShip.searchMagic(context, "application/x-font-ttf-plane0"); List<File> fonts = systemWarpShip.searchMagic(context, "application/x-font-ttf-plane0");
File systemFont = fonts.get(0); File systemFont = fonts.get(0);
@ -241,18 +245,25 @@ public class GDXAppTos4Activator implements BundleActivator {
} }
bootScreen.bootLine("gdx-font: "+parameter.characters.length()+" glyphs loaded."); bootScreen.bootLine("gdx-font: "+parameter.characters.length()+" glyphs loaded.");
context.registerService(SystemGdxFont.class.getName(), new SystemGdxFontImpl(gdxFont), new Hashtable<String, String>()); List<ServiceRegistration<?>> pistons = new ArrayList<>();
context.registerService(SystemGdxLog.class.getName(), systemGdxLog, new Hashtable<String, String>()); pistons.add(context.registerService(SystemGdxFont.class.getName(), new SystemGdxFontImpl(gdxFont), new Hashtable<String, String>()));
context.registerService(SystemGdxBootArgs.class.getName(), new SystemGdxBootArgsImpl(), new Hashtable<String, String>()); pistons.add(context.registerService(SystemGdxLog.class.getName(), systemGdxLog, new Hashtable<String, String>()));
context.registerService(SystemGdxTerminal.class.getName(), systemGdxTerminal, new Hashtable<String, String>()); pistons.add(context.registerService(SystemGdxBootArgs.class.getName(), new SystemGdxBootArgsImpl(), new Hashtable<String, String>()));
pistons.add(context.registerService(SystemGdxTerminal.class.getName(), systemGdxTerminal, new Hashtable<String, String>()));
bootScreen.bootLine("nx01-engine: Booted " + pistons.size() + " plasma cambers");
pistons.clear();
bootScreen.bootLine("nx01-bridge: Loading vrGEM4");
try { try {
Thread.sleep(1234+123);
systemWarpShip.loadBundles(context, registratedSeas); systemWarpShip.loadBundles(context, registratedSeas);
} catch (BundleException e) { } catch (Exception e) {
e.printStackTrace(); if (!GDXAppTos4.INSTANCE.isRunning()) {
return;
}
LOG.error(e.getMessage(), e);
startError(e.getMessage());
systemGdxTerminal.selectScreen(GDXAppTos4BootScreen.class); systemGdxTerminal.selectScreen(GDXAppTos4BootScreen.class);
bootScreen.bootLineError("ERROR: "+e.getMessage());
startError = true;
return; return;
} }
} }
@ -369,7 +380,7 @@ public class GDXAppTos4Activator implements BundleActivator {
logger.accept(infoResult); logger.accept(infoResult);
// if (!infoResult.startsWith("Drive Info")) { // if (!infoResult.startsWith("Drive Info")) {
// logger.accept("ERROR: Couldn't get info on: "+waterHome); // logger.accept("ERROR: Couldn't get info on: "+waterHome);
// return 1; // return -1;
// } // }
} else { } else {
waterHome = new File(override); waterHome = new File(override);
@ -379,25 +390,25 @@ public class GDXAppTos4Activator implements BundleActivator {
File waterHash = new File(waterHome, Warpᵐᵉ.WARP_HASH); File waterHash = new File(waterHome, Warpᵐᵉ.WARP_HASH);
if (!waterHash.exists()) { if (!waterHash.exists()) {
logger.accept("ERROR: Missing file: "+waterHash); logger.accept("ERROR: Missing file: "+waterHash);
return 1; return -1;
} }
WaterShotAddict addict = new WaterShotAddict(); WaterShotAddict addict = new WaterShotAddict();
try { try {
if (!addict.validateWarpChainLink(waterHome)) { if (!addict.validateWarpChainLink(waterHome)) {
logger.accept("ERROR: Invalid hash in: "+waterHash); logger.accept("ERROR: Invalid hash in: "+waterHash);
return 1; return -1;
} }
} catch (NoSuchAlgorithmException | X4OConnectionException | SAXException | IOException e) { } catch (NoSuchAlgorithmException | X4OConnectionException | SAXException | IOException e) {
e.printStackTrace(); e.printStackTrace();
logger.accept("ERROR: "+e.getMessage()); logger.accept("ERROR: "+e.getMessage());
return 1; return -1;
} }
File waterSea = new File(waterHome, Warpᵐᵉ.WARP_SEA); File waterSea = new File(waterHome, Warpᵐᵉ.WARP_SEA);
if (!waterSea.exists()) { if (!waterSea.exists()) {
logger.accept("ERROR: Missing file: "+waterSea); logger.accept("ERROR: Missing file: "+waterSea);
return 1; return -1;
} }
WaterOcean ocean = WaterOceanDriver.newInstance().createReader().readFile(waterSea); WaterOcean ocean = WaterOceanDriver.newInstance().createReader().readFile(waterSea);
logger.accept("water-ocean: "+key+" ("+ocean.theWater().getName()+")"); logger.accept("water-ocean: "+key+" ("+ocean.theWater().getName()+")");
@ -408,7 +419,7 @@ public class GDXAppTos4Activator implements BundleActivator {
context.registerService(SystemWarpSea.class.getName(), sea, props); context.registerService(SystemWarpSea.class.getName(), sea, props);
registratedSeas.add(sea); registratedSeas.add(sea);
int result = 0; int result = 1;
for (WaterSeaChain chain: ocean.theWater().getSeaChains()) { for (WaterSeaChain chain: ocean.theWater().getSeaChains()) {
result += loadWaterOcean(context, registratedSeas, chain.getKey(), logger); result += loadWaterOcean(context, registratedSeas, chain.getKey(), logger);
} }
@ -478,6 +489,11 @@ public class GDXAppTos4Activator implements BundleActivator {
} }
return result; return result;
} }
@Override
public boolean isRunning() {
return GDXAppTos4.INSTANCE.isRunning();
}
} }
public static class SystemGdxLogImpl implements SystemGdxLog, ApplicationLogger { public static class SystemGdxLogImpl implements SystemGdxLog, ApplicationLogger {

View file

@ -43,6 +43,8 @@ import ᒢᐩᐩ.ᔆʸᔆᐪᓫᔿ.ᒃᣔᒃᓫᒻ.ᑊᐣᓑᖮᐪᔆ.DuytsDocAu
@DuytsDocAuthor注(name = "للَّٰهِilLצسُو", copyright = "©Δ∞ 仙上主天") @DuytsDocAuthor注(name = "للَّٰهِilLצسُو", copyright = "©Δ∞ 仙上主天")
public interface SystemWarpShip { public interface SystemWarpShip {
boolean isRunning();
WaterDevice getWarpShip(); WaterDevice getWarpShip();
int loadWaterOcean(BundleContext context, List<SystemWarpSea> registratedSeas, String key, Consumer<String> logger) throws IOException, InterruptedException, X4OConnectionException, SAXException, BundleException; int loadWaterOcean(BundleContext context, List<SystemWarpSea> registratedSeas, String key, Consumer<String> logger) throws IOException, InterruptedException, X4OConnectionException, SAXException, BundleException;

View file

@ -66,8 +66,6 @@ import ᒢᐩᐩ.ᔆʸᔆᐪᓫᔿ.ᒃᣔᒃᓫᒻ.ᑊᐣᓑᖮᐪᔆ.DuytsDocAu
@DuytsDocAuthor注(name = "للَّٰهِilLצسُو", copyright = "©Δ∞ 仙上主天") @DuytsDocAuthor注(name = "للَّٰهِilLצسُو", copyright = "©Δ∞ 仙上主天")
public class GDXAppVrGem4Activator implements BundleActivator { public class GDXAppVrGem4Activator implements BundleActivator {
private static final int VIEW_SLEEP_TIME = 1234;
@Override @Override
public void stop(final BundleContext context) { public void stop(final BundleContext context) {
Gdx.app.postRunnable(new Runnable() { Gdx.app.postRunnable(new Runnable() {
@ -80,11 +78,6 @@ public class GDXAppVrGem4Activator implements BundleActivator {
@Override @Override
public void start(final BundleContext context) { public void start(final BundleContext context) {
try {
Thread.sleep(VIEW_SLEEP_TIME);
} catch (InterruptedException ignored) {
}
ServiceReference<SystemGdxLog> loggerRef = context.getServiceReference(SystemGdxLog.class); ServiceReference<SystemGdxLog> loggerRef = context.getServiceReference(SystemGdxLog.class);
SystemGdxLog logger = context.getService(loggerRef); SystemGdxLog logger = context.getService(loggerRef);
@ -120,21 +113,17 @@ public class GDXAppVrGem4Activator implements BundleActivator {
result = systemWarpShip.loadWaterOcean(context, registratedSeas, ocean.getSea(), v -> bootScreen.bootLine(v)); result = systemWarpShip.loadWaterOcean(context, registratedSeas, ocean.getSea(), v -> bootScreen.bootLine(v));
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); throw new IllegalStateException(e);
bootScreen.bootLine("ERROR: "+e.getMessage()); }
if (result < 0) {
bootScreen.bootLine("SPACE DOCK FAILURE, WARP SEA NAVIGATION ABORTED");
return; return;
} }
if (result > 0) { bootScreen.bootLine("vrGEM⁴: Resolved " + result + " chains");
bootScreen.bootLine("vrGEM4: FAILURE BOOT ABORTED");
return;
}
bootScreen.bootLine("vrGEM4: chains resolved.");
try { try {
systemWarpShip.loadBundles(context, registratedSeas); systemWarpShip.loadBundles(context, registratedSeas);
} catch (BundleException e) { } catch (BundleException e) {
e.printStackTrace(); throw new IllegalStateException(e);
bootScreen.bootLine("ERROR: "+e.getMessage());
return;
} }
bootArgs.addBootReadyListener(new SystemGdxBootReadyListener() { bootArgs.addBootReadyListener(new SystemGdxBootReadyListener() {
@Override @Override
@ -154,7 +143,7 @@ public class GDXAppVrGem4Activator implements BundleActivator {
unicodeService.init(context, systemWarpShip, (v) -> bootScreen.bootLine(v)); unicodeService.init(context, systemWarpShip, (v) -> bootScreen.bootLine(v));
context.registerService(VrGem4Unicode4DService.class.getName(), unicodeService, new Hashtable<String, String>()); context.registerService(VrGem4Unicode4DService.class.getName(), unicodeService, new Hashtable<String, String>());
startBundles(bootScreen); bootScreen.bootLine("vrGEM⁴: Loaded virtual space");
} }
private GDXAppVrGem4BootScreen createBootScreen(SystemGdxTerminal terminal, SystemGdxFont gdxFont) { private GDXAppVrGem4BootScreen createBootScreen(SystemGdxTerminal terminal, SystemGdxFont gdxFont) {
@ -167,10 +156,6 @@ public class GDXAppVrGem4Activator implements BundleActivator {
terminal.selectScreen(GDXAppVrGem4BootScreen.class); terminal.selectScreen(GDXAppVrGem4BootScreen.class);
} }
}); });
try {
Thread.sleep(100);
} catch (InterruptedException ignored) {
}
return bootScreen; return bootScreen;
} }
@ -238,18 +223,6 @@ public class GDXAppVrGem4Activator implements BundleActivator {
terminal.registrateScreen(new ScreenHelp(terminal)); terminal.registrateScreen(new ScreenHelp(terminal));
} }
}); });
try {
Thread.sleep(100);
} catch (InterruptedException ignored) {
}
}
private void startBundles(GDXAppVrGem4BootScreen bootScreen) {
try {
Thread.sleep(VIEW_SLEEP_TIME);
} catch (InterruptedException ignored) {
}
bootScreen.bootLine("vrGEM4: Init bundles...");
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View file

@ -63,6 +63,9 @@ public class VrGem4Unicode4DServiceImpl implements VrGem4Unicode4DService {
List<File> glyps = warpShip.searchMagic(context, "application/x-font-ttf4d"); List<File> glyps = warpShip.searchMagic(context, "application/x-font-ttf4d");
try { try {
for (File glypSet : glyps) { for (File glypSet : glyps) {
if (!warpShip.isRunning()) {
return;
}
log.accept("Loading glypSet: " + glypSet.getName()); log.accept("Loading glypSet: " + glypSet.getName());
FontAtlas atlas = FontAtlasDriver.newInstance().createReader().readFile(glypSet); FontAtlas atlas = FontAtlasDriver.newInstance().createReader().readFile(glypSet);
masterFontAtlas.setStores(atlas.getStores()); masterFontAtlas.setStores(atlas.getStores());
@ -75,6 +78,9 @@ public class VrGem4Unicode4DServiceImpl implements VrGem4Unicode4DService {
int dup = 0; int dup = 0;
for (FontAtlasStore fontStore:masterFontAtlas.getStores()) { for (FontAtlasStore fontStore:masterFontAtlas.getStores()) {
if (!warpShip.isRunning()) {
return;
}
log.accept("Map unicode: "+fontStore.getName()+" size: "+fontStore.getGlyphs().size()); log.accept("Map unicode: "+fontStore.getName()+" size: "+fontStore.getGlyphs().size());
for (FontAtlasStoreGlyph glyph: fontStore.getGlyphs()) { for (FontAtlasStoreGlyph glyph: fontStore.getGlyphs()) {
int unicode = CodePointᶻᴰ.INSTANCE.searchUnicode(glyph.getTongs()); int unicode = CodePointᶻᴰ.INSTANCE.searchUnicode(glyph.getTongs());

View file

@ -47,7 +47,7 @@ public class ScreenCredits extends AbstractScrollScreen {
"Bunnies have easter egg children with many colored seed spots", "Bunnies have easter egg children with many colored seed spots",
"...", "...",
" ", " ",
"=== BEGIN KJV PAGE ONE ===", "=== BEGIN OF KJV PAGE ONE ===",
" ", " ",
"### Genesis 1", "### Genesis 1",
" ", " ",
@ -288,9 +288,11 @@ public class ScreenCredits extends AbstractScrollScreen {
" ", " ",
"5 But unto Cain and to his offering he had not respect. And Cain was very wroth, and his countenance fell.", "5 But unto Cain and to his offering he had not respect. And Cain was very wroth, and his countenance fell.",
" ", " ",
"=== BEGIN KJV PAGE ONE ===", "=== END OF KJV PAGE ONE ===",
" ", " ",
"Page two requires consent for marriage.", "Page two requires consent for marriage;",
"- Information kills the heart",
"- Love is before the fall to the fruit",
" " " "
); );