struct DocServer = [ DOCSRV_port : I, DOCSRV_www : S, DOCSRV_sRoot : S, DOCSRV_sLang : S, DOCSRV_server : HTTPserver, DOCSRV_lVar : [[S [S]] r1], DOCSRV_lBaseVar : [[S S] r1] ]mkDocServer;; typeof MainDocServer = DocServer;; typeof lDocExportUrl = [S r1];; typeof lDocVars = [[S S] r1];; var sDocBaseHeader = "HTTP/1.0 200 OK\13\10Server: SCOL HTTP server\13\10";; var lDocMimesTypes = [nil "Content-Type: application/x-unknown"]:: ["html" "Content-Type: text/html"]:: ["jpeg" "Content-Type: image/jpeg"]:: ["jpg" "Content-Type: image/jpeg"]:: ["gif" "Content-Type: image/gif"]:: ["png" "Content-Type: image/png"]:: ["css" "Content-Type: text/css"]:: ["js" "Content-Type: text/javascript"]:: ["xml" "Content-Type: text/xml"]:: ["txt" "Content-Type: text/plain"]::nil;; var iMainDocPort = 885;; fun stopDocServer(dsrvstr)= let if (dsrvstr == nil) then MainDocServer else dsrvstr -> dsrvstr in ( closeHTTPserver dsrvstr.DOCSRV_server; if (MainDocServer != dsrvstr) then nil else set MainDocServer = nil; ); 0;; fun makeDocHeader(file)= let getFileExt file -> ext in let switchstri lDocMimesTypes ext -> mime in strcatn sDocBaseHeader::mime::"\13\10\13\10"::nil ;; fun getDocUrlParams(url)= let strfind "?" url 0 -> pos in let if (pos != nil) then (substr url 0 pos) else url -> baseurl in let strToListSep (substr url pos + 1 1024) "&" -> params in let nil -> cparams in ( while (params != nil) do ( let hd params -> param in let strfind "=" param 0 -> ppos in let if (ppos != nil) then (substr param 0 ppos) else param -> p in let if (ppos != nil) then (substr param ppos + 1 1024) else nil -> val in ( //addLogMessage strcatn "param : "::p::" value : "::val::nil; set cparams = lcat cparams [p val]::nil; ); set params = tl params; ); [(strtrim baseurl) cparams]; );; fun getDocPageDef(html)= let strfind " spos in let strfind "def/>" html spos -> dpos in if (spos == nil) then [nil html] else ( let substr html (spos + 4) (dpos - (spos + 4)) -> params in let strToList params -> lp in let nil -> np in ( while (lp != nil) do ( let hd lp -> ln in let strextr ln -> [[n nn] _] in if (nn == nil) then nil else ( let strlen n -> ns in let substr ln (ns + 1) (strlen ln) - ns -> val in ( //addLogMessage strcatn "Def: "::n::" > "::val::nil; set np = [n val]::np; ); ); set lp = tl lp; ); [np (substr html (dpos + 5) (strlen html) - (dpos + 5))] ); );; fun applyDocDef(html, ldef)= while (ldef != nil) do ( let hd ldef -> [p val] in set html = strreplace html (strcat "$" p) val; set ldef = tl ldef; ); html;; fun searchPlugByName(l, plugname)= if (l == nil) then nil else let l -> [[name plugstr] next] in if ((!strcmpi name plugname) || (!strcmpi (strreplace name " " "_") plugname) || (!strcmpi (strreplace name " " "") plugname)) then plugstr else searchPlugByName next plugname;; fun computeDocPlugIt(catname, plugname, alert)= let struppercase (strdup catname) -> uppercat in let substr uppercat 0 1 -> majc in let strcat majc (substr catname 1 1024) -> catnamec in let switchstri lPlugins plugname -> plugstr in let if (plugstr == nil) then searchPlugByName lPlugins plugname else plugstr -> plugstr in let struppercase (strdup plugstr.PLUG_sName) -> upperplug in let substr upperplug 0 1 -> majp in let strcat majp (substr plugstr.PLUG_sName 1 1024) -> plugnamec in let strcatn " $HEADER

""::(strtoutf8 plugnamec)::"" PlugIT

"::(if (plugstr == nil) then strcat "PlugIT not found: " plugname else (strtoutf8 (locPluginDesc plugstr)))::"

\n"::nil -> html in ( if ((plugstr != nil) || !alert) then nil else addLogMessage strcat "Missing plugin: " plugname; let sizelist plugstr.PLUG_lParams -> lpsize in if (lpsize == 0) then nil else ( set html = strcatn html::" "::nil; let 0 -> i in while (i < lpsize) do ( let nth_list plugstr.PLUG_lParams i -> [p _] in set html = strcatn html::" "::nil; set i = i + 1; ); set html = strcat html "
 

"::(strtoutf8 loc "OS3D_0805")::"

"::(itoa (i + 1))::"

"::p::"

"; ); let sizelist plugstr.PLUG_lAction -> lpsize in if (lpsize == 0) then nil else ( set html = strcatn html::"
"::nil; let 0 -> i in while (i < lpsize) do ( let nth_list plugstr.PLUG_lAction i -> p in set html = strcatn html::" "::nil; set i = i + 1; ); set html = strcat html "
 

"::(strtoutf8 loc "OS3D_0806")::"

"::p::"

TODO

"; ); let sizelist plugstr.PLUG_lEvent -> lpsize in if (lpsize == 0) then nil else ( set html = strcatn html::"
"::nil; let 0 -> i in while (i < lpsize) do ( let nth_list plugstr.PLUG_lEvent i -> p in set html = strcatn html::" "::nil; set i = i + 1; ); set html = strcat html "
 

"::(strtoutf8 loc "OS3D_0807")::"

"::p::"

TODO

"; ); strcat html "\n\n$FOOTER"; );; fun getDocPlugitFromUrl(url)= let strfind "/plugits/" url 0 -> ppos in if (ppos == nil) then nil else ( let strfind "/" url (ppos + 9) -> lastp in let strfind ".html" url (lastp + 1) -> endp in let substr url (ppos + 9) (lastp - (ppos + 9)) -> catname in let substr url (lastp + 1) (endp - (lastp + 1)) -> plugname in [catname plugname]; );; fun getDocUrlDirectories(url)= let 0 -> lpos in let 0 -> nbdir in ( while (lpos != nil) do ( set lpos = lpos + 1; let strfind "/" url lpos -> pend in let substr url lpos (pend - lpos) -> dir in ( if ((pend == nil) || (!strcmp dir "")) then nil else ( if (!strcmp dir "..") then set nbdir = nbdir - 1 else set nbdir = nbdir + 1; ); set lpos = strfind "/" url pend; ); ); let "" -> reldir in ( let 0 -> i in while (i < nbdir) do ( set reldir = strcat reldir "../"; set i = i + 1; ); //addLogMessage strcatn url::" to "::reldir::nil; reldir; ); );; fun computeDocPage(dsrvstr, baseurl, params, alert)= let _getpack _checkpack (strcatn dsrvstr.DOCSRV_www::"/"::dsrvstr.DOCSRV_sLang::baseurl::nil) -> html in let if (html != nil) then html else _getpack _checkpack (strcat dsrvstr.DOCSRV_www baseurl) -> html in let if (html == nil) then let getDocPlugitFromUrl baseurl -> ret in if (ret == nil) then nil else let ret -> [catn plugn] in computeDocPlugIt catn plugn alert else html -> html in if (html == nil) then ( if (!alert) then nil else addLogMessage strcat "Missing page: " baseurl; nil; ) else let getDocPageDef html -> [ldef html] in let applyDocDef html ldef -> html in ( //while (params != nil) do //( // let hd params -> [p val] in // // p webtostr val nil; // // set params = tl params; //); let 0 -> i in let sizelist dsrvstr.DOCSRV_lVar -> size in while (i < size) do ( let nth_list dsrvstr.DOCSRV_lVar i -> [p [val]] in let applyDocDef val ldef -> val in ( //addLogMessage strcatn "apply var: "::p::" > "::val::nil; set html = strreplace html (strcat "$" p) val; ); set i = i + 1; ); let getDocUrlDirectories baseurl -> reldir in strreplace html "$ROOT" reldir; //strreplace html "$ROOT" dsrvstr.DOCSRV_sRoot; );; fun cbDocRequest(conx, dsrvstr, req)= let hd strextr req -> l in let l->[com [url _]] in let getDocUrlParams url -> [baseurl params] in let if (!strcmp baseurl "/") then "/index.html" else baseurl -> baseurl in ( if (!strcmpi com "GET") then ( let computeDocPage dsrvstr baseurl params 0 -> html in if (html == nil) then ( //addLogMessage strcat "Doc server file not found: " (strcatn dsrvstr.DOCSRV_www::"/"::dsrvstr.DOCSRV_sLang::baseurl::nil); strcatn (makeDocHeader "/404.html")::"File not found : 404

404 file not found:

"::(strcatn dsrvstr.DOCSRV_www::"/"::dsrvstr.DOCSRV_sLang::baseurl::nil)::"."::nil ) else strcat (makeDocHeader baseurl) html; ) else if (!strcmpi com "POST") then { ""; } else ""; );; fun cbDocSaveVar(dsrvstr, name, value)= let switchstri dsrvstr.DOCSRV_lVar name -> vart in mutate vart <- [value]; 0;; fun cbSortDocVars(m1, m2)= let m1 -> [act1 _] in let m2 -> [act2 _] in (strcmp act1 act2) <= 0;; fun cbSortDocPlugIts(s1, s2)= strcmpi s1.PLUG_sName s2.PLUG_sName;; var lExcludeDocCategory = "gametools"::"anr"::"jizen"::"pise"::"studec"::nil;; var lExcludeDocPlugIts = "emotiondetector"::"eyetracking"::"respirationbelt"::"nonin"::"vlc"::"oculus"::"materialreflection"::"deferred"::"tutorial"::"webrequest"::"physicstructure"::"terrain"::nil;; fun getPlugItsByCat(dsrvstr)= let nil -> nlcat in let nil -> nlplugscat in let lPlugins -> lplugs in ( while (lplugs != nil) do ( let hd lplugs -> [name plugstr] in let getlastPathDir plugstr.PLUG_sDir -> pdir in if ((plugstr.PLUG_bHasError) || (!strcmp plugstr.PLUG_sHelp "") || (isStringInList lExcludeDocCategory plugstr.PLUG_sType) || (isStringInList lExcludeDocPlugIts pdir)) then nil else ( set nlcat = plugstr.PLUG_sType::nlcat; let switchstr nlplugscat plugstr.PLUG_sType -> cf in if (cf == nil) then ( set nlplugscat = [plugstr.PLUG_sType [plugstr::nil]]::nlplugscat; 0; ) else ( let cf -> [lp] in mutate cf <- [plugstr::lp]; 0; ); ); set lplugs = tl lplugs; ); set nlcat = quicksort nlcat @suppDoublon; [nlcat nlplugscat]; );; fun getPlugITsUrls(dsrvstr)= let getPlugItsByCat dsrvstr -> [nlcat nlplugscat] in let nil -> lurls in ( while (nlcat != nil) do ( let hd nlcat -> catname in let struppercase strdup catname -> upper in let strreplace catname " " "_" -> catnamel in ( let switchstr nlplugscat catname -> [cf] in let "" -> htmlp in ( set cf = quicksort cf @cbSortDocPlugIts; while (cf != nil) do ( let hd cf -> plugstr in let plugstr.PLUG_sName -> pname in let strlowercase strdup pname -> lower in let strreplace lower " " "_" -> pnamel in let strreplace catname " " "_" -> catnamel in let getPathFile plugstr.PLUG_sHelp "" -> [_ filename] in let if ((filename == nil) || (!strcmp filename "")) then nil else strcatn dsrvstr.DOCSRV_www::"/"::dsrvstr.DOCSRV_sLang::"/plugits/"::catnamel::"/"::filename::nil -> fpath in let if ((fpath == nil) || (_checkpack fpath) == nil) then strcatn dsrvstr.DOCSRV_www::"/"::dsrvstr.DOCSRV_sLang::"/plugits/"::catnamel::"/"::pnamel::".html"::nil else fpath -> fpath in set lurls = fpath::lurls; set cf = tl cf; ); ); ); set nlcat = tl nlcat; ); lurls; );; fun loadPlugItsCategories(dsrvstr)= let "" -> htmlcat in let getPlugItsByCat dsrvstr -> [nlcat nlplugscat] in let 0 -> nb in ( while (nlcat != nil) do ( let hd nlcat -> catname in let struppercase strdup catname -> upper in let strreplace catname " " "_" -> catnamel in let substr upper 0 1 -> maj in let strcat maj (substr catname 1 1024) -> catnamec in ( let switchstr nlplugscat catname -> [cf] in let "" -> htmlp in ( let strcatn dsrvstr.DOCSRV_www::"/"::dsrvstr.DOCSRV_sLang::"/plugits/"::catnamel::"/index.html"::nil -> ipath in //if ((_checkpack ipath) == nil) then nil else ( set cf = quicksort cf @cbSortDocPlugIts; while (cf != nil) do ( let hd cf -> plugstr in let plugstr.PLUG_sName -> pname in let strlowercase strdup pname -> lower in let strreplace lower " " "_" -> pnamel in let struppercase strdup pname -> pupper in let strreplace catname " " "_" -> catnamel in let substr pupper 0 1 -> pmaj in let strcat pmaj (substr pname 1 1024) -> pnamec in let getPathFile plugstr.PLUG_sHelp "" -> [_ filename] in let strcatn dsrvstr.DOCSRV_www::"/"::dsrvstr.DOCSRV_sLang::"/plugits/"::catnamel::"/"::filename::nil -> fpath in let if ((_checkpack fpath) == nil) then strcat pnamel ".html" else filename -> pnamel in set htmlp = strcatn htmlp::""::(strtoutf8 pnamec)::"

"::(strtoutf8 (locPluginDesc plugstr))::"

\n"::nil; set cf = tl cf; set nb = nb + 1; ); set dsrvstr.DOCSRV_lVar = [strcatn "PLUGITCAT_"::upper::"_SUMMARY"::nil [htmlp]]::dsrvstr.DOCSRV_lVar; set htmlcat = strcatn htmlcat::"

"::(strtoutf8 (locDef catname catnamec))::"

\n"::nil; ); ); ); set nlcat = tl nlcat; ); //set htmlcat = strcatn htmlcat::"

"::(itoa nb)::" PlugITs in documentation

\n"::nil; set dsrvstr.DOCSRV_lVar = ["PLUGITCAT_SUMMARY" [htmlcat]]::dsrvstr.DOCSRV_lVar; ); 0;; fun startDocServer(port, path, root, lang, lvar)= let mkDocServer [port path root lang nil nil lvar] -> dsrvstr in ( let sizelist lvar -> size in let 0 -> i in while i < size do ( let nth_list lvar i -> [name value] in ( set dsrvstr.DOCSRV_lVar = [name [value]]::dsrvstr.DOCSRV_lVar; ); set i = i + 1; ); set dsrvstr.DOCSRV_lVar = sortlist dsrvstr.DOCSRV_lVar @cbSortDocVars; set dsrvstr.DOCSRV_lVar = revertlist dsrvstr.DOCSRV_lVar; loadPlugItsCategories dsrvstr; let _getpack _checkpack (strcatn dsrvstr.DOCSRV_www::"/"::dsrvstr.DOCSRV_sLang::"/footer.inc"::nil) -> footer in if (footer == nil) then nil else set dsrvstr.DOCSRV_lVar = ["FOOTER" [footer]]::dsrvstr.DOCSRV_lVar; let _getpack _checkpack (strcatn dsrvstr.DOCSRV_www::"/"::dsrvstr.DOCSRV_sLang::"/header.inc"::nil) -> header in if (header == nil) then nil else set dsrvstr.DOCSRV_lVar = ["HEADER" [header]]::dsrvstr.DOCSRV_lVar; while ((set dsrvstr.DOCSRV_server = startHTTPserver _channel dsrvstr.DOCSRV_port @cbDocRequest dsrvstr) == nil) do set dsrvstr.DOCSRV_port = dsrvstr.DOCSRV_port + 1; dsrvstr; );; fun setDocServerLang(dsrvstr, lang)= let if (dsrvstr == nil) then MainDocServer else dsrvstr -> dsrvstr in ( set dsrvstr.DOCSRV_sLang = lang; let sizelist dsrvstr.DOCSRV_lBaseVar -> size in let 0 -> i in while i < size do ( let nth_list dsrvstr.DOCSRV_lBaseVar i -> [name value] in ( set dsrvstr.DOCSRV_lVar = [name [value]]::dsrvstr.DOCSRV_lVar; ); set i = i + 1; ); set dsrvstr.DOCSRV_lVar = sortlist dsrvstr.DOCSRV_lVar @cbSortDocVars; set dsrvstr.DOCSRV_lVar = revertlist dsrvstr.DOCSRV_lVar; loadPlugItsCategories dsrvstr; let _getpack _checkpack (strcatn dsrvstr.DOCSRV_www::"/"::dsrvstr.DOCSRV_sLang::"/footer.inc"::nil) -> footer in if (footer == nil) then nil else set dsrvstr.DOCSRV_lVar = ["FOOTER" [footer]]::dsrvstr.DOCSRV_lVar; let _getpack _checkpack (strcatn dsrvstr.DOCSRV_www::"/"::dsrvstr.DOCSRV_sLang::"/header.inc"::nil) -> header in if (header == nil) then nil else set dsrvstr.DOCSRV_lVar = ["HEADER" [header]]::dsrvstr.DOCSRV_lVar; dsrvstr; );; fun startMainDocServer()= //addLogMessage loc "OS3D_0800"; let ["OS3DVERSION" getVersionName]::["OS3DDATE" getVersionDate]::["PAGE_TITLE" "OpenSpace3D Documentation"]::["BACK_LINK" ""]::["BACK_TEXT" ""]::nil -> lvar in set MainDocServer = startDocServer iMainDocPort (strcat APPBASEDIR "os3deditor/doc") "/" (loc "LANGCODE") lvar; //addLogMessage loc "OS3D_0801"; 0;; fun isDocServerAvailable(dsrvstr)= if (dsrvstr.DOCSRV_server == nil) then 0 else 1;; fun isMainDocServerAvailable()= if (MainDocServer.DOCSRV_server == nil) then 0 else 1;; fun cleanDocUrlDirectories(url)= let 0 -> lpos in let 0 -> nbdir in let nil -> ldir in ( while (lpos != nil) do ( set lpos = lpos + 1; let strfind "/" url lpos -> pend in let substr url lpos (pend - lpos) -> dir in ( if ((pend == nil) || (!strcmp dir "")) then nil else ( if (!strcmp dir "..") then set ldir = tl ldir else set ldir = lcat ldir dir::nil; ); set lpos = strfind "/" url pend; ); ); let getPathFile url "" -> [dir filename] in let strcatnSep ldir "/" -> cpath in if ((cpath == nil) || (!strcmp cpath "")) then ( //addLogMessage strcatn "Clean url: "::url::" to "::(strcat "/" filename)::nil; strcat "/" filename ) else ( //addLogMessage strcatn "Clean url: "::url::" to "::(strcatn "/"::cpath::"/"::filename::nil)::nil; strcatn "/"::cpath::"/"::filename::nil; ); );; fun getDocResources(dsrvstr, path, html)= let getPathFile path "" -> [fpath _] in let strlen dsrvstr.DOCSRV_sRoot -> rsize in let 0 -> lpos in let nil -> lfiles in let nil -> lpages in ( while ((set lpos = strfind "href=\"" html lpos) != nil) do ( set lpos = lpos + 6; let strfind "\"" html lpos -> pend in let substr html lpos (pend - lpos) -> url in if (!strcmp (substr url 0 8) "https://") || (!strcmp (substr url 0 7) "http://") || (!strcmp (substr url 0 7) "file://") || (!strcmp (substr url 0 6) "ftp://") then nil else ( let if (!strcmp "/" (substr url 0 1)) then url else strcat fpath url -> url in let if (!strcmp dsrvstr.DOCSRV_sRoot (substr url 0 rsize)) then (substr url rsize ((strlen url) - rsize)) else url -> url in let cleanDocUrlDirectories url -> url in if ((strlen url) <= 1) then nil else ( //addLogMessage strcat "Found page: " url; let getFileExt url -> ext in if (!strcmp ext "html") then set lpages = url::lpages else set lfiles = url::lfiles; ); set lpos = pend; ); ); let 0 -> lpos in while ((set lpos = strfind "src=\"" html lpos) != nil) do ( set lpos = lpos + 5; let strfind "\"" html lpos -> pend in let substr html lpos (pend - lpos) -> ourl in if (!strcmp (substr ourl 0 8) "https://") || (!strcmp (substr ourl 0 7) "http://") || (!strcmp (substr ourl 0 7) "file://") || (!strcmp (substr ourl 0 6) "ftp://") then nil else ( let if (!strcmp "/" (substr ourl 0 1)) then ourl else strcat fpath ourl -> url in let if (!strcmp dsrvstr.DOCSRV_sRoot (substr url 0 rsize)) then (substr url rsize ((strlen url) - rsize)) else url -> url in let cleanDocUrlDirectories url -> url in if ((strlen url) <= 1) then nil else ( let substr html 0 lpos -> ht1 in let substr html pend ((strlen html) - pend) -> ht2 in set html = strcatn ht1::(strlowercase ourl)::ht2::nil; //addLogMessage strcat "Found img: " url; set lfiles = url::lfiles; ); ); ); [html lfiles lpages] );; fun getDocRecursivePages(dsrvstr, dstpath, lp)= if (lp == nil) then nil else let hd lp -> page in if (isStringInList lDocExportUrl page) then getDocRecursivePages dsrvstr dstpath tl lp else let computeDocPage dsrvstr page nil 1 -> index in let getDocResources dsrvstr page index -> [index lfiles lpages] in ( //addLogMessage strcat "Write doc: " page; _storepack index strcatn dstpath::page::nil; set lDocExportUrl = page::lDocExportUrl; while (lfiles != nil) do ( let hd lfiles -> file in let _checkpack (strcat dsrvstr.DOCSRV_www file) -> pfile in let if (pfile == nil) then _checkpack strcatn dsrvstr.DOCSRV_www::"/"::dsrvstr.DOCSRV_sLang::file::nil else pfile -> pfile in if (pfile != nil) then ( _storepack (_getpack pfile) strcat dstpath file; 0; ) else ( addLogMessage strcat "Missing file: " file; 0; ); set lfiles = tl lfiles; ); getDocRecursivePages dsrvstr dstpath lpages; getDocRecursivePages dsrvstr dstpath tl lp; ); 0;; fun getDocRecursiveTemplatePages(dsrvstr, dstpath, lp)= if (lp == nil) then nil else ( let hd lp -> page in if (isStringInList lDocExportUrl page) then getDocRecursiveTemplatePages dsrvstr dstpath tl lp else let _getpack _checkpack page -> html in let if (html == nil) then let getDocPlugitFromUrl page -> ret in if (ret == nil) then nil else let ret -> [catn plugn] in computeDocPlugIt catn plugn 1 else nil -> template in if (template == nil) then nil else ( addLogMessage strcat "Write doc: " page; _storepack template strcatn page::nil; set lDocExportUrl = page::lDocExportUrl; //while (lfiles != nil) do //( // let hd lfiles -> file in // let _checkpack (strcat dsrvstr.DOCSRV_www file) -> pfile in // let if (pfile == nil) then // _checkpack strcatn dsrvstr.DOCSRV_www::"/"::dsrvstr.DOCSRV_sLang::file::nil // else // pfile // -> pfile in // if (pfile != nil) then // ( // _storepack (_getpack pfile) strcat dstpath file; // 0; // ) // else // ( // addLogMessage strcat "Missing file: " file; // 0; // ); // // set lfiles = tl lfiles; //); //getDocRecursiveTemplatePages dsrvstr dstpath lpages; 0; ); getDocRecursiveTemplatePages dsrvstr dstpath tl lp; ); 0;; fun computeAllDoc(dsrvstr, dstpath, root)= let if (dsrvstr == nil) then MainDocServer else dsrvstr -> dsrvstr in ( addLogMessage strcatn "Generating documentation for "::dsrvstr.DOCSRV_sLang::" language"::nil; set dsrvstr.DOCSRV_sRoot = strcatn root::dsrvstr.DOCSRV_sLang::nil; let strcatn dstpath::"/"::dsrvstr.DOCSRV_sLang::nil -> dstpath in getDocRecursivePages dsrvstr dstpath "/index.html"::nil; if (MainDocServer != dsrvstr) then nil else set dsrvstr.DOCSRV_sRoot = "/"; set lDocExportUrl = nil; addLogMessage "Generating documentation done!"; ); 0;; fun computeAllMissingDoc(dsrvstr, dstpath, root)= let if (dsrvstr == nil) then MainDocServer else dsrvstr -> dsrvstr in ( addLogMessage strcatn "Generating missing documentation for "::dsrvstr.DOCSRV_sLang::" language"::nil; set dsrvstr.DOCSRV_sRoot = strcatn root::dsrvstr.DOCSRV_sLang::nil; let strcatn dstpath::"/"::dsrvstr.DOCSRV_sLang::nil -> dstpath in getDocRecursiveTemplatePages dsrvstr dstpath (getPlugITsUrls dsrvstr); if (MainDocServer != dsrvstr) then nil else set dsrvstr.DOCSRV_sRoot = "/"; set lDocExportUrl = nil; addLogMessage "Generating missing documentation done!"; ); 0;;