Sometimes it is better to solve a problem with hardware (relay) instead of software.
The hardware way:
You put a relay down stream of the M3 pin and control the relay with another pin.  The relay should have a normally closed contact and a normally open contact.
Relay not energized == M3 will control the spindle:  
                 /------ -> Spindle motor start.
m3 -> ----/
                  ------ -> Router motor start.  
Relay energized == M3 controls the router.
                  ------ -> Spindle motor start.
m3 -> ----\
                 \ ------ -> Router motor start.  
                 
You use another output(pin) to energize/de-energize this relay.  This was from the concept I replied with on you first post about this dual Z machine.  
The software way:
You can remap a signal from one physical output to another with API calls.  Port2/pin14 and port2/pin17 are mapped to a Mach output singlanls, right?  These are usually mapped in the Input and Output signal tabs of the config dialog.  
Take a look at mcSignalMap() and mcSignalUnmap().  Used this in conjuction with mcSingalGetHandle() and mcIoGetHandle()
function mapSpindleFwd(to)
	local inst = mc.mcGetInstance('MyPinSwapProggy')
	local oSigSpindleCW = mc.OSIG_SPINDLEFWD -- constant for the output signal you are using with M3 (usually spindle forward)
	local hSigSpinfleCW = 0 -- The handle to the spindle forward signal
	local rc = mc.MERROR_NOERROR -- our return code variable.  It is VERY imporatant to check the API return codes!!!!
	
	local hIoSpindle = 0 -- The handle to port2/pin14
	local hIoRouter = 0 -- The handle to port2/pin17
	-- Set the following to the real path in the form of devName/ioName
	-- Get this information from the output signal mapping tab of the config dialog.  
	local pathSpindle = 'dev/port2-pin14' 
	local pathRouter = 'dev/port2-pin14' 
	
	hSigSpinfleCW, rc = mc.mcSignalGetHandle(inst, oSigSpindleCW)
	if (rc ~= mc.MERROR_NOERROR) then 
		mc.mcCntlSetLastError(inst, 'Failed to get the spindle fwd handle.')
		return(rc) -- error out
	end
	
	-- Now to do the actual deed...
	rc = mc.mcSignalUnmap(hSigSpinfleCW); -- unmap the existing signal.
	if (rc ~= mc.MERROR_NOERROR) then 
		mc.mcCntlSetLastError(inst, 'Failed to unmap the spindle fwd signal.')
		return(rc) -- error out
	end
	
	if (to == 0) then 
		hIoSpindle, rc = mc.mcIoGetHandle(inst, pathSpindle)
		if (rc ~= mc.MERROR_NOERROR) then 
			mc.mcCntlSetLastError(inst, 'Failed to get the spindle I/O handle.')
			return(rc) -- error out
		end
		-- Map spindle forward to the spindle.
		rc = mc.mcSignalMap(hSigSpinfleCW, hIoSpindle)
		if (rc ~= mc.MERROR_NOERROR) then 
			mc.mcCntlSetLastError(inst, 'Failed to map the spindle fwd signal to the spindle.')
			return(rc) -- error out
		end
	elseif  (to == 1) then 
		hIoRouter, rc = mc.mcIoGetHandle(inst, pathRouter)
		if (rc ~= mc.MERROR_NOERROR) then 
			mc.mcCntlSetLastError(inst, 'Failed to get the router I/O handle.')
			return(rc) -- error out
		end
		rc = mc.mcSignalMap(hSigSpinfleCW, hIoRouter)
		if (rc ~= mc.MERROR_NOERROR) then 
			mc.mcCntlSetLastError(inst, 'Failed to map the spindle fwd signal to the spindle.')
			return(rc) -- error out
		end
	else 
		mc.mcCntlSetLastError(inst, 'Invalid parameter value!')
		return(mc.MERROR_INVALID_PARAM) -- error out
	end
	return(mc.MERROR_NOERROR) -- success
end
-- example usage
local toSpindle = 0 -- sometimes setting up constants is easier to read later on!!!  
local toRouter = 1
rc = mapSpindleFwd(toSpindle) -- maps M3 to the spindle output.
rc = mapSpindleFwd(toRouter) -- maps M3 to the router output.