func TestParse3(t *testing.T) { dbg.InitLogging(0) relish.InitRuntime("relish.db") builtin.InitBuiltinFunctions() var g *Generator for _, filename := range validFiles { fileNode, err := parser.ParseFile(fset, filename, nil, parser.DeclarationErrors|parser.Trace) if err != nil { t.Errorf("ParseFile(%s): %v", filename, err) } ast.Print(fset, fileNode) fileNameRoot := filename[:len(filename)-4] g = NewGenerator(fileNode, fileNameRoot) g.GenerateCode() //g.TestWalk() } g.Interp.RunMain() }
func main() { var loggingLevel int var webListeningPort int var tlsWebListeningPort int var shareListeningPort int // port on which source code will be shared by http var sharedCodeOnly bool // do not use local artifacts - only those in shared directory. var explorerListeningPort int // port on which data explorer_api web service will be served. var runningArtifactMustBeFromShared bool var dbName string var cpuprofile string var publish bool var quiet bool var projectPath string // var gcIntervalSeconds int //var fset = token.NewFileSet() flag.IntVar(&loggingLevel, "log", 0, "The logging level: 0 is least verbose, 2 most") flag.IntVar(&webListeningPort, "web", 0, "The http listening port - if not supplied, does not listen for http requests") flag.IntVar(&tlsWebListeningPort, "tls", 0, "The https listening port - if not supplied, does not listen for https requests") flag.IntVar(&explorerListeningPort, "explore", 0, "The explorer_api web service listening port - if supplied, the data explorer tool can connect to this program on this port") flag.StringVar(&dbName, "db", "db1", "The database name. A SQLITE database file called <name>.db will be created/used in artifact data directory") flag.BoolVar(&sharedCodeOnly, "shared", false, "Use shared version of all artifacts - ignore local/dev copy of artifacts") flag.StringVar(&cpuprofile, "cpuprofile", "", "write cpu profile to file") flag.IntVar(&shareListeningPort, "share", 0, "The code sharing http listening port - if not supplied, does not listen for source code sharing http requests") flag.BoolVar(&publish, "publish", false, "artifactpath version - copy specified version of artifact to shared/relish/artifacts") flag.BoolVar(&quiet, "quiet", false, "do not show package loading info or interpreter version in program output") flag.StringVar(&projectPath, "init", "", "<artifactpath> [webapp] - create directory tree and template files for a relish software project") flag.IntVar(¶ms.GcIntervalSeconds, "gc", params.GcIntervalSeconds, "The garbage collection check interval (seconds): defaults to 20") flag.IntVar(¶ms.DbMaxConnections, "pool", params.DbMaxConnections, "Maximum number of db connections to open with the database: defaults to 1") flag.IntVar(¶ms.DbMaxReadConnections, "rpool", params.DbMaxReadConnections, "Maximum number of read-only db connections to open with the database") flag.IntVar(¶ms.DbMaxWriteConnections, "wpool", params.DbMaxWriteConnections, "Maximum number of writeable db connections to open with the database") flag.Parse() pathParts := flag.Args() // full path to package, or originAndArtifact and path to package // (or originAndArtifact and version number if -publish) if cpuprofile != "" { f, err := gos.Create(cpuprofile) if err != nil { fmt.Println(err) return } pprof.StartCPUProfile(f) defer pprof.StopCPUProfile() } dbg.InitLogging(int32(loggingLevel)) //relish.InitRuntime("relish.db") // if ! publish { // builtin.InitBuiltinFunctions() // } var g *generator.Generator var relishRoot string // This actually has to be the root of the runtime environment // i.e. /opt/relish if this is a binary distribution, // or /opt/relish/rt if this is a source distribution workingDirectory, err := gos.Getwd() if err != nil { fmt.Printf("Cannot determine working directory: %s\n", err) } var originAndArtifact string var version string var packagePath string isSubDir := false isSourceDist := false relishIndexInWd := strings.Index(workingDirectory, "/relish/") if relishIndexInWd > -1 { isSubDir = true } else { relishIndexInWd = strings.Index(workingDirectory, "/relish") if relishIndexInWd == -1 || relishIndexInWd != len(workingDirectory)-7 { if projectPath != "" { // Must be creating a relish dir under a new project dir relishRoot = workingDirectory + "/relish" err = gos.MkdirAll(relishRoot, 0777) if err != nil { fmt.Printf("Error making relish project directory %s: %s\n", relishRoot, err) return } } else { fmt.Printf("relish command must be run from within a relish directory tree.\n") return } } } if relishRoot == "" { relishRoot = workingDirectory[:relishIndexInWd+7] } _, err = gos.Stat(relishRoot + "/rt") if err == nil { relishRoot += "/rt" isSourceDist = true } else if !os.IsNotExist(err) { fmt.Printf("Can't stat '%s' : %v\n", relishRoot+"/rt", err) return } // relishRoot is now established if projectPath != "" { if len(pathParts) < 1 { err = initProject(relishRoot, projectPath, "") if err == nil { fmt.Printf("\nCreated relish project template\n%s/artifacts/%s\n", relishRoot, projectPath) fmt.Printf("\nTo run your project template's dummy main program, relish %s\n\n", projectPath) } else { fmt.Printf("\nError initializing project %s: %s\n", projectPath, err) } } else { projectType := pathParts[0] err = initProject(relishRoot, projectPath, projectType) if err == nil { fmt.Printf("\nCreated relish web-app project template\n%s/artifacts/%s\n", relishRoot, projectPath) fmt.Printf("\nTo run the web-app, relish -web 8080 %s\n", projectPath) fmt.Printf("Then enter localhost:8080 into your browser's address bar to view the web app.\n\n") } else { fmt.Printf("\nError initializing project %s: %s\n", projectPath, err) } } return } if isSubDir { // See where we are more specifically if isSourceDist { idx := strings.Index(workingDirectory, "/rt/shared") if idx > -1 { runningArtifactMustBeFromShared = true } } else { idx := strings.Index(workingDirectory, "/relish/shared") if idx > -1 { runningArtifactMustBeFromShared = true } } if !publish { // See if the current directory is a particular artifact version directory, // or even is a particular package directory. originPos := strings.Index(workingDirectory, "/artifacts/") + 11 if originPos == 10 { originPos = strings.Index(workingDirectory, "/replicas/") + 10 } if originPos >= 10 { match := reVersionedPackage.FindStringSubmatchIndex(workingDirectory) if match != nil { version = workingDirectory[match[2]:match[3]] originAndArtifact = workingDirectory[originPos:match[0]] packagePath = workingDirectory[match[3]+1:] } else { match := reVersionAtEnd.FindStringSubmatch(workingDirectory) if match != nil { version = match[1] originAndArtifact = workingDirectory[originPos : len(workingDirectory)-len(version)-2] } } } } } if !publish { builtin.InitBuiltinFunctions(relishRoot) } crypto_util.SetRelishRuntimeLocation(relishRoot) // So that keys can be fetched. if publish { if len(pathParts) < 2 { fmt.Println("Usage (example): relish -publish someorigin.com2013/artifact_name 1.0.23") return } originAndArtifact = pathParts[0] version = pathParts[1] if strings.HasSuffix(originAndArtifact, "/") { // Strip trailing / if present originAndArtifact = originAndArtifact[:len(originAndArtifact)-1] } err = global_publisher.PublishSourceCode(relishRoot, originAndArtifact, version) if err != nil { fmt.Println(err) } return } sourceCodeShareDir := "" if shareListeningPort != 0 { // sourceCodeShareDir hould be the "relish/shared" // or "relish/rt/shared" of "relish/4production/shared" or "relish/rt/4production/shared" directory. sourceCodeShareDir = relishRoot + "/shared" } onlyCodeSharing := (shareListeningPort != 0 && webListeningPort == 0 && tlsWebListeningPort == 0) if onlyCodeSharing { if shareListeningPort < 1024 && shareListeningPort != 80 { fmt.Println("Error: The source-code sharing port must be 80 or > 1023 (8421 is the standard if using a high port)") return } web.ListenAndServeSourceCode(shareListeningPort, sourceCodeShareDir) // The previous call should wait on incoming socket connections on the specified port, and never return. // If get here, we had a PORT binding problem. Perhaps relish (running as current user) does not // have permission to listen on a < 1024 port like port 80. fmt.Printf("Error: Could not bind to port %d to listen for http connections.\n"+ "Did you setup to give relish permission to bind to privileged ports?\n"+ "or is another process already listening on this port?\n", shareListeningPort) return } var loader = global_loader.NewLoader(relishRoot, sharedCodeOnly, dbName+".db", quiet) if originAndArtifact == "" { if len(pathParts) == 3 { // originAndArtifact version packagePath originAndArtifact = pathParts[0] version = pathParts[1] packagePath = pathParts[2] } else if len(pathParts) == 2 { // originAndArtifact packagePath originAndArtifact = pathParts[0] packagePathOrVersion := pathParts[1] // Determine if is a version by regexp or a package path has been supplied version = reVersion.FindString(packagePathOrVersion) if version == "" { packagePath = packagePathOrVersion } } else if shareListeningPort == 0 || webListeningPort != 0 || tlsWebListeningPort != 0 { if len(pathParts) != 1 { fmt.Println("Usage: relish [-web 80] originAndArtifact [version] [path/to/package]\n# package path defaults to main") return } originAndArtifact = pathParts[0] } } else if packagePath == "" { if len(pathParts) == 1 { packagePath = pathParts[0] } else if len(pathParts) > 1 { fmt.Println("Usage (when in an artifact version directory): relish [-web 80] [path/to/package]\n# package path defaults to main") return } } else { // both originAndArtifact and packagePath are defined (non "") if len(pathParts) != 0 { fmt.Println("Usage (when in a package directory): relish [-web 80]") return } } if strings.HasSuffix(originAndArtifact, "/") { // Strip trailing / if present originAndArtifact = originAndArtifact[:len(originAndArtifact)-1] } if strings.HasSuffix(packagePath, "/") { // Strip trailing / if present packagePath = packagePath[:len(packagePath)-1] } if packagePath == "" { packagePath = "main" // substitute a default. } fullPackagePath := fmt.Sprintf("%s/v%s/pkg/%s", originAndArtifact, version, packagePath) fullUnversionedPackagePath := fmt.Sprintf("%s/pkg/%s", originAndArtifact, packagePath) g, err = loader.LoadPackage(originAndArtifact, version, packagePath, runningArtifactMustBeFromShared) if err != nil { if version == "" { fmt.Printf("Error loading package %s from current version of %s: %v\n", packagePath, originAndArtifact, err) } else { fmt.Printf("Error loading package %s: %v\n", fullPackagePath, err) } return } g.Interp.SetRunningArtifact(originAndArtifact) g.Interp.SetPackageLoader(loader) // TODO the following rather twisty logic (from here to end of main method) could be straightened out. // One of its purposes is to ensure that the last http listener is run in this goroutine rather // than in a background one. And there can be different numbers of listeners... // Count how many separate listeners there will be. numListeners := 0 numListening := 0 // how many of those are already listening? if webListeningPort != 0 { numListeners += 1 if shareListeningPort != 0 && shareListeningPort != webListeningPort { numListeners += 1 } } if tlsWebListeningPort != 0 { numListeners += 1 } if explorerListeningPort != 0 { numListeners += 1 } // end counting listeners // check for disallowed port numbers, and if not, load the packages needed for web app serving if webListeningPort != 0 { if webListeningPort < 1024 && webListeningPort != 80 { fmt.Println("Error: The web listening port must be 80 or > 1023") return } if shareListeningPort != webListeningPort && shareListeningPort != 0 && shareListeningPort < 1024 && shareListeningPort != 80 { fmt.Println("Error: The source-code sharing port must be 80 or > 1023 (8421 is the standard if using a high port)") return } } if tlsWebListeningPort != 0 { if tlsWebListeningPort < 1024 && tlsWebListeningPort != 443 { fmt.Println("Error: The tls web listening port must be 443 or > 1023") return } } if webListeningPort != 0 || tlsWebListeningPort != 0 { err = loader.LoadWebPackages(originAndArtifact, version, runningArtifactMustBeFromShared) if err != nil { if version == "" { fmt.Printf("Error loading web packages from current version of %s: %v\n", originAndArtifact, err) } else { fmt.Printf("Error loading web packages from version %s of %s: %v\n", version, originAndArtifact, err) } return } } // check for disallowed port numbers, and if not, load the package needed for explorer_api web service serving if explorerListeningPort != 0 { if explorerListeningPort < 1024 && explorerListeningPort != 80 { fmt.Println("Error: The explorer listening port must be 80 or > 1023") return } explorerApiOriginAndArtifact := "shared.relish.pl2012/explorer_api" explorerApiPackagePath := "web" _, err = loader.LoadPackage(explorerApiOriginAndArtifact, "", explorerApiPackagePath, false) if err != nil { fmt.Printf("Error loading package %s from current version of %s: %v\n", explorerApiPackagePath, explorerApiOriginAndArtifact, err) return } } if numListeners > 0 { // If we'll be listening for http requests, run main in a background goroutine. go g.Interp.RunMain(fullUnversionedPackagePath, quiet) } if webListeningPort != 0 || tlsWebListeningPort != 0 { web.SetWebPackageSrcDirPath(loader.PackageSrcDirPath(originAndArtifact + "/pkg/web")) if webListeningPort != 0 { if shareListeningPort == webListeningPort { numListening += 1 if numListening == numListeners { web.ListenAndServe(webListeningPort, sourceCodeShareDir) // The previous call should wait on incoming socket connections on the specified port, and never return. // If get here, we had a PORT binding problem. Perhaps relish (running as current user) does not // have permission to listen on a < 1024 port like port 80. fmt.Printf("Error: Could not bind to port %d to listen for http connections.\n"+ "Did you setup to give relish permission to bind to privileged ports?\n"+ "or is another process already listening on this port?\n", webListeningPort) return } else { go web.ListenAndServe(webListeningPort, sourceCodeShareDir) } } else { if shareListeningPort != 0 { numListening += 1 go web.ListenAndServeSourceCode(shareListeningPort, sourceCodeShareDir) } numListening += 1 if numListening == numListeners { web.ListenAndServe(webListeningPort, "") // The previous call should wait on incoming socket connections on the specified port, and never return. // If get here, we had a PORT binding problem. Perhaps relish (running as current user) does not // have permission to listen on a < 1024 port like port 80. fmt.Printf("Error: Could not bind to port %d to listen for http connections.\n"+ "Did you setup to give relish permission to bind to privileged ports?\n"+ "or is another process already listening on this port?\n", webListeningPort) return } else { go web.ListenAndServe(webListeningPort, "") } } } if tlsWebListeningPort != 0 { tlsCertPath, tlsKeyPath, err := crypto_util.GetTLSwebServerCertAndKeyFilePaths() if err != nil { fmt.Printf("Error starting TLS web listener: %s\n", err) return } numListening += 1 if numListening == numListeners { web.ListenAndServeTLS(tlsWebListeningPort, tlsCertPath, tlsKeyPath) // The previous call should wait on incoming socket connections on the specified port, and never return. // If get here, we had a PORT binding problem. Perhaps relish (running as current user) does not // have permission to listen on a < 1024 port like port 80. fmt.Printf("Error: Could not bind to port %d to listen for https connections.\n"+ "Did you setup to give relish permission to bind to privileged ports?\n"+ "or is another process already listening on this port?\n", tlsWebListeningPort) return } else { go web.ListenAndServeTLS(tlsWebListeningPort, tlsCertPath, tlsKeyPath) } } } if explorerListeningPort != 0 { web.ListenAndServeExplorerApi(explorerListeningPort) // The previous call should wait on incoming socket connections on the specified port, and never return. // If get here, we had a PORT binding problem. Perhaps relish (running as current user) does not // have permission to listen on a < 1024 port like port 80. fmt.Printf("Error: Could not bind to port %d to listen for http connections.\n"+ "Did you setup to give relish permission to bind to privileged ports?\n"+ "or is another process already listening on this port?\n", explorerListeningPort) return } // This will only be reached if numListeners == 0 or there is an error starting listeners. // but don't want to re-run main if there was an error starting listeners. if numListeners == 0 { g.Interp.RunMain(fullUnversionedPackagePath, quiet) } }