summary refs log blame commit diff stats
path: root/nim/options.pas
blob: d03a24f2a533c56032c2d3951b4e27d1c7ea6713 (plain) (tree)
1
2
3
4


                                
                                          










                                                    
                                          



                                              

                                            

                                 







                                                                              

                                                                    





                                                                         
                                                       

                                                    


                                                                         
                                                                      
                                                      

                                                            






                                        
                           
                     










                                                         
                                                             
                                                            
                                               
    
                               

     


                                                                       
                                            
                                                               


                                                                     
                                               

    

                                                                        
                                                            



                                                           






                                           
                                                 
                                                   



                                           
                         


                   
                 
                 
                           
                                  




                                                                      
                                                                            




                                      
   
                            
                       
                           
                                                                             
                                                        

                                                 
                                                  
                                                 
                                               








                                                                         




                                                  

                                                 
                                           



                                               
                                      

    






















                                                         












                                                         





                                                         








                                                                         

    




                                                          

                                                                
                                                







                                                                      


                                                               
                            







                                                              
      


                                  
                                              














                                      






                                           




















                                                                         

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

interface

{$include 'config.inc'}

uses
  nsystem, nos, lists, strutils, nstrtabs;

type
  // please make sure we have under 32 options
  // (improves code efficiency a lot!)
  TOption = (  // **keep binary compatible**
    optNone,
    optObjCheck,
    optFieldCheck, optRangeCheck,
    optBoundsCheck, optOverflowCheck, optNilCheck, 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 records (for interfacing with C)
    optCheckpoints,    // check for checkpoints (used for debugging)
    optProfiler        // profiler turned on
  );
  TOptions = set of TOption;

  TGlobalOption = (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 of TGlobalOption;

  TCommands = ( // 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 = array of string;

const
  ChecksOptions = {@set}[optObjCheck, optFieldCheck, optRangeCheck,
                         optNilCheck, optOverflowCheck, optBoundsCheck,
                         optAssert];
  optionToStr: array [TOption] of string = (
    'optNone', 'optObjCheck', 'optFieldCheck', 'optRangeCheck',
    'optBoundsCheck', 'optOverflowCheck', 'optNilCheck', 'optAssert',
    'optLineDir', 'optWarns', 'optHints', 'optOptimizeSpeed',
    'optOptimizeSize', 'optStackTrace', 'optLineTrace', 'optEmdb',
    'optByRef', 'optCheckpoints', 'optProfiler'
  );
var
  gOptions: TOptions = {@set}[optObjCheck, optFieldCheck, optRangeCheck,
                              optBoundsCheck, optOverflowCheck,
                              optAssert, optWarns, optHints,
                              optStackTrace, optLineTrace];

  gGlobalOptions: TGlobalOptions = {@set}[optRefcGC];

  gExitcode: Byte;
  searchPaths: TLinkedList;
  outFile: string = '';
  gIndexFile: string = '';

  gCmd: TCommands = cmdNone; // the command

  gVerbosity: int; // how verbose the compiler is
  gNumberOfProcessors: int; // number of processors

function FindFile(const f: string): string;

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

function completeGeneratedFilePath(const f: string;
                                   createSubDir: bool = true): string;

function toGeneratedFile(const path, ext: string): string;
// converts "/home/a/mymodule.nim", "rod" to "/home/a/nimcache/mymodule.rod"

function getPrefixDir: string;
// gets the application directory

// additional configuration variables:
var
  gConfigVars: PStringTable;
  libpath: string = '';
  projectPath: string = '';
  gKeepComments: boolean = true; // whether the parser needs to keep comments
  gImplicitMods: TStringSeq = {@ignore} nil {@emit @[]};
    // modules that are to be implicitly imported

function existsConfigVar(const key: string): bool;
function getConfigVar(const key: string): string;
procedure setConfigVar(const key, val: string);

procedure addImplicitMod(const filename: string);

function getOutFile(const filename, ext: string): string;

function binaryStrSearch(const x: array of string; const y: string): int;

implementation

function existsConfigVar(const key: string): bool;
begin
  result := hasKey(gConfigVars, key)
end;

function getConfigVar(const key: string): string;
begin
  result := nstrtabs.get(gConfigVars, key);
end;

procedure setConfigVar(const key, val: string);
begin
  nstrtabs.put(gConfigVars, key, val);
end;

function getOutFile(const filename, ext: string): string;
begin
  if options.outFile <> '' then result := options.outFile
  else result := changeFileExt(filename, ext)
end;

procedure addImplicitMod(const filename: string);
var
  len: int;
begin
  len := length(gImplicitMods);
  setLength(gImplicitMods, len+1);
  gImplicitMods[len] := filename;
end;

function getPrefixDir: string;
var
  appdir, bin: string;
begin
  appdir := getApplicationDir();
  SplitPath(appdir, result, bin);
end;

function shortenDir(const dir: string): string;
var 
  prefix: string;
begin
  // returns the interesting part of a dir
  prefix := getPrefixDir() +{&} dirSep;
  if startsWith(dir, prefix) then begin
    result := ncopy(dir, length(prefix) + strStart); exit
  end;
  prefix := getCurrentDir() +{&} dirSep;
  if startsWith(dir, prefix) then begin
    result := ncopy(dir, length(prefix) + strStart); exit
  end;
  prefix := projectPath +{&} dirSep;
  //writeln(output, prefix);
  //writeln(output, dir);
  if startsWith(dir, prefix) then begin
    result := ncopy(dir, length(prefix) + strStart); exit
  end;
  result := dir;
end;

function removeTrailingDirSep(const path: string): string;
begin
  if (length(path) > 0) and (path[length(path)+strStart-1] = dirSep) then
    result := ncopy(path, strStart, length(path)+strStart-2)
  else
    result := path
end;

function toGeneratedFile(const path, ext: string): string;
var
  head, tail: string;
begin
  splitPath(path, head, tail);
  if length(head) > 0 then head := shortenDir(head +{&} dirSep);
  result := joinPath([projectPath, genSubDir, head, 
                      changeFileExt(tail, ext)])
end;

function completeGeneratedFilePath(const f: string;
                                   createSubDir: bool = true): string;
var
  head, tail, subdir: string;
begin
  splitPath(f, head, tail);
  if length(head) > 0 then
    head := removeTrailingDirSep(shortenDir(head +{&} dirSep));
  subdir := joinPath([projectPath, genSubDir, head]);
  if createSubDir then begin
    try
      createDir(subdir);
    except
      on EOS do begin
        writeln(output, 'cannot create directory: ' + subdir);
        halt(1)
      end
    end
  end;
  result := joinPath(subdir, tail)
end;

function rawFindFile(const f: string): string;
var
  it: PStrEntry;
begin
  if ExistsFile(f) then result := f
  else begin
    it := PStrEntry(SearchPaths.head);
    while it <> nil do begin
      result := JoinPath(it.data, f);
      if ExistsFile(result) then exit;
      it := PStrEntry(it.Next)
    end;
    result := ''
  end
end;

function FindFile(const f: string): string;
begin
  result := rawFindFile(f);
  if length(result) = 0 then
    result := rawFindFile(toLower(f));
end;

function binaryStrSearch(const x: array of string; const y: string): int;
var
  a, b, mid, c: int;
begin
  a := 0;
  b := length(x)-1;
  while a <= b do begin
    mid := (a + b) div 2;
    c := cmpIgnoreCase(x[mid], y);
    if c < 0 then
      a := mid + 1
    else if c > 0 then
      b := mid - 1
    else begin
      result := mid;
      exit
    end
  end;
  result := -1
end;

initialization
  gConfigVars := newStringTable([], modeStyleInsensitive);
end.