
1 // 2 // Copyright (c) 2006, Brian Frank and Andy Frank 3 // Licensed under the Academic Free License version 3.0 4 // 5 // History: 6 // 15 Sep 05 Brian Frank Creation 7 // 3 Jun 06 Brian Frank Ported from Java to Fan - Megan's b-day 8 // 9 10 ** 11 ** Main is the main entry point for the Fan compiler. It handles 12 ** all the argument processing and misc commands like help, version, 13 ** 14 class Main 15 { 16 17 ////////////////////////////////////////////////////////////////////////// 18 // Run 19 ////////////////////////////////////////////////////////////////////////// 20 21 ** 22 ** Main entry point for compiler. 23 ** 24 Int run(Str[] args) 25 { 26 t1 := Duration.now 27 success := true 28 29 // process args 30 if (!parseArgs(args)) return 0 31 32 // process each directory specified 33 try 34 { 35 compile 36 } 37 catch (CompilerErr err) 38 { 39 // all errors should already be logged by Compiler 40 success = false; 41 } 42 catch (Err err) 43 { 44 log.compilerErr(CompilerErr.make("Internal compiler error", null, err)); 45 err.trace 46 success = false; 47 } 48 49 t2 := Duration.now 50 if (success) 51 { 52 println("SUCCESS (" + (t2-t1).toMillis + "ms)") 53 return 0 54 } 55 else 56 { 57 println("FAILED (" + (t2-t1).toMillis + "ms)") 58 return -1 59 } 60 } 61 62 ** 63 ** Process command line args and return false if we should exit. 64 ** 65 Bool parseArgs(Str[] args) 66 { 67 if (args.isEmpty) 68 { 69 help 70 return false 71 } 72 73 for (i:=0; i<args.size; ++i) 74 { 75 a := args[i] 76 if (a.isEmpty) continue 77 if (a == "-help" || a == "-h" || a == "-?") 78 { 79 help 80 return false 81 } 82 else if (a == "-version") 83 { 84 version 85 return false 86 } 87 else if (a == "-d") 88 { 89 if (i+1 >= args.size) 90 { 91 println("ERROR: must specified dir with -d option") 92 return false 93 } 94 outDir = File.make(args[++i].toUri).normalize 95 } 96 else if (a == "-src") 97 { 98 includeSrc = true 99 } 100 else if (a == "-doc") 101 { 102 includeDoc = true 103 } 104 else if (a == "-v") 105 { 106 log.level = LogLevel.debug 107 } 108 else if (a == "-silent") 109 { 110 log.level = LogLevel.silent 111 } 112 else if (a[0] == '-') 113 { 114 println("WARNING: Unknown option " + a) 115 } 116 else 117 { 118 if (podName == null) 119 podName = a 120 else 121 srcDirs.add(File.make(a.toUri)) 122 } 123 } 124 125 // if no dirs were specified, assume current dir 126 if (podName == null || srcDirs.isEmpty) 127 { 128 println("ERROR: not enough arguments") 129 help 130 return false 131 } 132 133 return true 134 } 135 136 ** 137 ** Dump help usage. 138 ** 139 Void help() 140 { 141 println("Fan Compiler (the one written in Fan itself)") 142 println("Usage:") 143 println(" ffanc [options] <podName> <srcDir>*") 144 println("Options:") 145 println(" -help, -h, -? print usage help") 146 println(" -version print version information") 147 println(" -d <dir> output directory for pod file") 148 println(" -doc include fandoc in pod") 149 println(" -src include source code in pod") 150 println(" -v verbose debug mode (more logging)") 151 println(" -silent silent mode (no logging)") 152 } 153 154 ** 155 ** Dump version. 156 ** 157 Void version() 158 { 159 println("Fan Compiler - Version ${type.pod.version}") 160 println("Copyright (c) 2006, Brian Frank and Andy Frank") 161 println("Licensed under the Academic Free License version 3.0") 162 } 163 164 ** 165 ** Compile using current configuration 166 ** 167 Void compile() 168 { 169 input := CompilerInput.make 170 input.podName = podName 171 input.log = log 172 input.mode = CompilerInputMode.file 173 input.homeDir = srcDirs.first.parent 174 input.srcDirs = srcDirs 175 input.includeDoc = includeDoc 176 input.includeSrc = includeSrc 177 input.output = CompilerOutputMode.podFile 178 if (outDir != null) input.outDir = outDir 179 180 Compiler.make(input).compile 181 } 182 183 ** 184 ** Compile the script file into a transient pod 185 ** 186 static Pod compileScript(File file) 187 { 188 input := CompilerInput.make 189 input.podName = "script_$file.basename" 190 input.log.level = LogLevel.error 191 input.isScript = true 192 input.srcStr = file.readAllStr 193 input.srcStrLocation = Location.makeFile(file) 194 input.mode = CompilerInputMode.str 195 input.output = CompilerOutputMode.transientPod 196 return Compiler.make(input).compile.transientPod 197 } 198 199 ////////////////////////////////////////////////////////////////////////// 200 // Utils 201 ////////////////////////////////////////////////////////////////////////// 202 203 Void println(Obj s) 204 { 205 log.printLine(s) 206 } 207 208 ////////////////////////////////////////////////////////////////////////// 209 // Main 210 ////////////////////////////////////////////////////////////////////////// 211 212 static Void main() 213 { 214 Sys.exit(make.run(Sys.args)) 215 } 216 217 ////////////////////////////////////////////////////////////////////////// 218 // Fields 219 ////////////////////////////////////////////////////////////////////////// 220 221 Str podName 222 File[] srcDirs := File[,] // directories to build 223 File outDir := null // -d output directory 224 CompilerLog log := CompilerLog.make // logging, -v verbose output 225 Bool includeDoc := false // include fandoc in output pod 226 Bool includeSrc := false // include source code in output pod 227 228 }