summary refs log tree commit diff stats
path: root/compiler/service.nim
blob: b1741b7bd1af5e9848115a3994f98e2a9d4f4539 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#
#
#           The Nimrod Compiler
#        (c) Copyright 2012 Andreas Rumpf
#
#    See the file "copying.txt", included in this
#    distribution, for details about the copyright.
#

## Implements the "compiler as a service" feature.

import 
  sockets,
  times, commands, options, msgs, nimconf,
  extccomp, strutils, os, platform, main, parseopt

# We cache modules and the dependency graph. However, we don't check for
# file changes but expect the client to tell us about them, otherwise the
# repeated CRC calculations may turn out to be too slow.

var 
  arguments*: string = ""     # the arguments to be passed to the program that
                              # should be run

proc ProcessCmdLine*(pass: TCmdLinePass, cmd: string) =
  var p = parseopt.initOptParser(cmd)
  var argsCount = 0
  while true: 
    parseopt.next(p)
    case p.kind
    of cmdEnd: break 
    of cmdLongOption, cmdShortOption: 
      # hint[X]:off is parsed as (p.key = "hint[X]", p.val = "off")
      # we fix this here
      var bracketLe = strutils.find(p.key, '[')
      if bracketLe >= 0: 
        var key = substr(p.key, 0, bracketLe - 1)
        var val = substr(p.key, bracketLe + 1) & ':' & p.val
        ProcessSwitch(key, val, pass, gCmdLineInfo)
      else: 
        ProcessSwitch(p.key, p.val, pass, gCmdLineInfo)
    of cmdArgument:
      if argsCount == 0:
        options.command = p.key
      else:
        if pass == passCmd1: options.commandArgs.add p.key
        if argsCount == 1:
          # support UNIX style filenames anywhere for portable build scripts:
          options.gProjectName = unixToNativePath(p.key)
          arguments = cmdLineRest(p)
          break
      inc argsCount
          
  if pass == passCmd2:
    if optRun notin gGlobalOptions and arguments != "":
      rawMessage(errArgsNeedRunOption, [])

proc serve*(action: proc (){.nimcall.}) =
  var server = Socket()
  let p = getConfigVar("server.port")
  let port = if p.len > 0: parseInt(p).TPort else: 6000.TPort
  server.bindAddr(port, getConfigVar("server.address"))
  var inp = "".TaintedString
  server.listen()
  new(stdoutSocket)
  while true:
    accept(server, stdoutSocket)
    discard stdoutSocket.recvLine(inp)
    processCmdLine(passCmd2, inp.string)
    action()
    stdoutSocket.send("\c\L")
    stdoutSocket.close()