summary refs log blame commit diff stats
path: root/rod/options.nim
blob: 15bca38b60dd3b75dc7a740b4c8affe5308d0c99 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16















                                                                         


                                               


                                                                             

                                                           






























                                                                                 
                                                                          









































































































































                                                                                
#
#
#           The Nimrod Compiler
#        (c) Copyright 2009 Andreas Rumpf
#
#    See the file "copying.txt", included in this
#    distribution, for details about the copyright.
#

import 
  os, lists, strutils, nstrtabs

type                          # please make sure we have under 32 options
                              # (improves code efficiency a lot!)
  TOption* = enum             # **keep binary compatible**
    optNone, optObjCheck, optFieldCheck, optRangeCheck, optBoundsCheck, 
    optOverflowCheck, optNilCheck,
    optNaNCheck, optInfCheck,
    optAssert, optLineDir, optWarns, optHints, 
    optOptimizeSpeed, optOptimizeSize, optStackTrace, # stack tracing support
    optLineTrace,             # line tracing support (includes stack tracing)
    optEndb,                  # embedded debugger
    optByRef,                 # use pass by ref for objects
                              # (for interfacing with C)
    optCheckpoints,           # check for checkpoints (used for debugging)
    optProfiler               # profiler turned on
  TOptions* = set[TOption]
  TGlobalOption* = enum 
    gloptNone, optForceFullMake, optBoehmGC, optRefcGC, optDeadCodeElim, 
    optListCmd, optCompileOnly, optNoLinking, optSafeCode, # only allow safe code
    optCDebug,                # turn on debugging information
    optGenDynLib,             # generate a dynamic library
    optGenGuiApp,             # generate a GUI application
    optGenScript,             # generate a script file to compile the *.c files
    optGenMapping,            # generate a mapping file
    optRun,                   # run the compiled project
    optSymbolFiles,           # use symbol files for speeding up compilation
    optSkipConfigFile,        # skip the general config file
    optSkipProjConfigFile,    # skip the project's config file
    optNoMain                 # do not generate a "main" proc
  TGlobalOptions* = set[TGlobalOption]
  TCommands* = enum           # Nimrod's commands
    cmdNone, cmdCompileToC, cmdCompileToCpp, cmdCompileToEcmaScript, 
    cmdCompileToLLVM, cmdInterpret, cmdPretty, cmdDoc, cmdPas, cmdBoot, 
    cmdGenDepend, cmdListDef, cmdCheck, # semantic checking for whole project
    cmdParse,                 # parse a single file (for debugging)
    cmdScan,                  # scan a single file (for debugging)
    cmdDebugTrans,            # debug a transformation pass
    cmdRst2html,              # convert a reStructuredText file to HTML
    cmdRst2tex,               # convert a reStructuredText file to TeX
    cmdInteractive            # start interactive session
  TStringSeq* = seq[string]

const 
  ChecksOptions* = {optObjCheck, optFieldCheck, optRangeCheck, optNilCheck, 
    optOverflowCheck, optBoundsCheck, optAssert, optNaNCheck, optInfCheck}

var 
  gOptions*: TOptions = {optObjCheck, optFieldCheck, optRangeCheck, 
                         optBoundsCheck, optOverflowCheck, optAssert, optWarns, 
                         optHints, optStackTrace, optLineTrace}
  gGlobalOptions*: TGlobalOptions = {optRefcGC}
  gExitcode*: int8
  searchPaths*: TLinkedList
  outFile*: string = ""
  gIndexFile*: string = ""
  gCmd*: TCommands = cmdNone  # the command
  gVerbosity*: int            # how verbose the compiler is
  gNumberOfProcessors*: int   # number of processors

proc FindFile*(f: string): string

const 
  genSubDir* = "nimcache"
  NimExt* = "nim"
  RodExt* = "rod"
  HtmlExt* = "html"
  TexExt* = "tex"
  IniExt* = "ini"
  DocConfig* = "nimdoc.cfg"
  DocTexConfig* = "nimdoc.tex.cfg"

proc completeGeneratedFilePath*(f: string, createSubDir: bool = true): string
proc toGeneratedFile*(path, ext: string): string
  # converts "/home/a/mymodule.nim", "rod" to "/home/a/nimcache/mymodule.rod"
proc getPrefixDir*(): string
  # gets the application directory

# additional configuration variables:
var 
  gConfigVars*: PStringTable
  libpath*: string = ""
  projectPath*: string = ""
  gKeepComments*: bool = true # whether the parser needs to keep comments
  gImplicitMods*: TStringSeq = @ [] # modules that are to be implicitly imported

proc existsConfigVar*(key: string): bool
proc getConfigVar*(key: string): string
proc setConfigVar*(key, val: string)
proc addImplicitMod*(filename: string)
proc getOutFile*(filename, ext: string): string
proc binaryStrSearch*(x: openarray[string], y: string): int
# implementation

proc existsConfigVar(key: string): bool = 
  result = hasKey(gConfigVars, key)

proc getConfigVar(key: string): string = 
  result = nstrtabs.get(gConfigVars, key)

proc setConfigVar(key, val: string) = 
  nstrtabs.put(gConfigVars, key, val)

proc getOutFile(filename, ext: string): string = 
  if options.outFile != "": result = options.outFile
  else: result = changeFileExt(filename, ext)
  
proc addImplicitMod(filename: string) = 
  var length: int
  length = len(gImplicitMods)
  setlen(gImplicitMods, length + 1)
  gImplicitMods[length] = filename

proc getPrefixDir(): string = 
  result = SplitPath(getApplicationDir()).head

proc shortenDir(dir: string): string = 
  # returns the interesting part of a dir
  var prefix = getPrefixDir() & dirSep
  if startsWith(dir, prefix): 
    return copy(dir, len(prefix) + 0)
  prefix = getCurrentDir() & dirSep
  if startsWith(dir, prefix): 
    return copy(dir, len(prefix) + 0)
  prefix = projectPath & dirSep #writeln(output, prefix);
                                #writeln(output, dir);
  if startsWith(dir, prefix): 
    return copy(dir, len(prefix) + 0)
  result = dir

proc removeTrailingDirSep(path: string): string = 
  if (len(path) > 0) and (path[len(path) + 0 - 1] == dirSep): 
    result = copy(path, 0, len(path) + 0 - 2)
  else: 
    result = path
  
proc toGeneratedFile(path, ext: string): string = 
  var (head, tail) = splitPath(path)
  if len(head) > 0: head = shortenDir(head & dirSep)
  result = joinPath([projectPath, genSubDir, head, changeFileExt(tail, ext)])

proc completeGeneratedFilePath(f: string, createSubDir: bool = true): string = 
  var (head, tail) = splitPath(f)
  if len(head) > 0: head = removeTrailingDirSep(shortenDir(head & dirSep))
  var subdir = joinPath([projectPath, genSubDir, head])
  if createSubDir: 
    try: 
      createDir(subdir)
    except EOS: 
      writeln(stdout, "cannot create directory: " & subdir)
      quit(1)
  result = joinPath(subdir, tail)

proc rawFindFile(f: string): string = 
  var it: PStrEntry
  if ExistsFile(f): 
    result = f
  else: 
    it = PStrEntry(SearchPaths.head)
    while it != nil: 
      result = JoinPath(it.data, f)
      if ExistsFile(result): return 
      it = PStrEntry(it.Next)
    result = ""

proc FindFile(f: string): string = 
  result = rawFindFile(f)
  if len(result) == 0: result = rawFindFile(toLower(f))
  
proc binaryStrSearch(x: openarray[string], y: string): int = 
  var a = 0
  var b = len(x) - 1
  while a <= b: 
    var mid = (a + b) div 2
    var c = cmpIgnoreCase(x[mid], y)
    if c < 0: 
      a = mid + 1
    elif c > 0: 
      b = mid - 1
    else: 
      return mid
  result = - 1

gConfigVars = newStringTable([], modeStyleInsensitive)