"Fossies" - the Fresh Open Source Software Archive

Member "pstoedit-3.78/src/callgs.cpp" (6 Nov 2021, 20290 Bytes) of package /linux/misc/pstoedit-3.78.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "callgs.cpp" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.77_vs_3.78.

    1 /*  
    2    callgs.cpp : This file is part of pstoedit
    3    interface to Ghostscript
    4 
    5    Copyright (C) 1993 - 2021 Wolfgang Glunz, wglunz35_AT_pstoedit.net
    6    
    7    Proposal for a "cleaned up" version: removed (IMHO) dead/old code,
    8    e.g., WIN32 is "dll only" now, because gs32 comes w/DLL 
    9 
   10    Extended for OS/2
   11 
   12     This program is free software; you can redistribute it and/or modify
   13     it under the terms of the GNU General Public License as published by
   14     the Free Software Foundation; either version 2 of the License, or
   15     (at your option) any later version.
   16 
   17     This program is distributed in the hope that it will be useful,
   18     but WITHOUT ANY WARRANTY; without even the implied warranty of
   19     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   20     GNU General Public License for more details.
   21 
   22     You should have received a copy of the GNU General Public License
   23     along with this program; if not, write to the Free Software
   24     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   25 
   26 */
   27 
   28 #include "cppcomp.h"
   29 
   30 #include I_iostream
   31 #include I_fstream
   32 
   33 #include "pstoedit.h"
   34 
   35 #include I_stdlib
   36 
   37 #include I_string_h
   38 
   39 
   40 // rcw2:Can't put angle brackets onto commandline for g++ on RiscOS :(
   41 #ifdef riscos
   42 #ifndef DEFAULTGS
   43 #define DEFAULTGS <GhostScript$Dir>.ghost
   44 #endif
   45 #endif
   46 
   47 
   48 #include "miscutil.h"
   49 //extern char *getRegistryValue(ostream & errstream, const char *typekey, const char *key);
   50 
   51 
   52 
   53 static RSString createCmdLine(int argc, const char *const argv[])
   54 {
   55     // create a single string from all args
   56     RSString result("");
   57     for (unsigned int i = 0; i < (unsigned) argc; i++) {
   58             result += argv[i];
   59             result += " ";
   60     }
   61     return result;
   62 }
   63 
   64 
   65 #if defined(_WIN32) || defined (__OS2__)
   66 
   67 // using Ghostscript DLL
   68 #define WITHDLLSUPPORT 1
   69 
   70 #ifdef WITHDLLSUPPORT
   71 
   72 #ifndef USEOLDAPI
   73     #include "callgsdllviaiapi.cpp"
   74 #else
   75 // version which uses obsolete API and gsdll.h
   76     #include "dwmaincgsdll.c"
   77 #endif
   78 
   79 #endif
   80 
   81 
   82 #if defined(_WIN32)
   83 // retrieve version to be used from registry
   84 #include "wgsver.c"         // ONLY WINDOWS
   85 #endif
   86 
   87 // #undef main
   88 
   89 #define WITHGETINI
   90 #ifdef WITHGETINI
   91 #include "getini.c"
   92 #endif
   93 
   94 
   95 
   96 // Interface to Ghostscript EXE - as an alternative to the DLL
   97 // The usage of the DLL makes problem in case of gsview, since 
   98 // there can only be one instance of the DLL and Ghostscript active
   99 // in one process. So - if being called from gsview - we need to start 
  100 // Ghostscript via the EXE.
  101 // Same holds if 64 bit Ghostscript should be called from 32 big pstoedit.
  102 #include <windows.h>
  103 #include I_stdio
  104 static int callgsEXE(int argc, const char * const argv[])
  105 {
  106     int gsresult = 0;
  107     STARTUPINFO MyStartupInfo; // process data
  108     memset(&MyStartupInfo,'\0',sizeof(MyStartupInfo));
  109     MyStartupInfo.cb = sizeof(STARTUPINFO);
  110     MyStartupInfo.wShowWindow=SW_SHOWMINNOACTIVE;
  111 
  112     PROCESS_INFORMATION MyProcessInformation;
  113          // CreateProcess fills in this structure
  114     DWORD gs_status = 0;
  115 
  116     const RSString& commandline = createCmdLine(argc,argv);
  117     cerr << "running-win x command line: " << commandline << endl;
  118 
  119     BOOL status = CreateProcess(
  120               nullptr, // Application Name 
  121 #ifdef OS_WIN32_WCE
  122               LPSTRtoLPWSTR((LPSTR)commandline.c_str()).c_str(),
  123 #else
  124               (LPSTR)commandline.c_str(),
  125 #endif
  126               nullptr, // Process attributes (NULL == Default)
  127               nullptr, // Thread-Attributes (Default)
  128               FALSE, // InheritHandles
  129               CREATE_NEW_PROCESS_GROUP, // CreationFlags
  130               nullptr, // Environment (NULL: same as calling-process)
  131               nullptr, // Current Directory (NULL: same as calling process)
  132               (LPSTARTUPINFO)(&MyStartupInfo), // Windows-state at Startup
  133                   // window of calling process gets minimized + and shown disabled
  134              (LPPROCESS_INFORMATION)(&MyProcessInformation)
  135             );
  136 
  137     if (status) gsresult=0;
  138     else        gsresult=-1; // Failure
  139 
  140     for ( ; ; ) { // while true but without compiler warning
  141         status=GetExitCodeProcess(MyProcessInformation.hProcess, &gs_status);
  142         if ( !status ) {  // process-Status could not be determined
  143             gsresult=-1;
  144             break;  
  145         } else if (gs_status==STILL_ACTIVE) { // gs still working
  146             Sleep(500); // polling interval
  147         } else break; // process terminated
  148     }
  149     if (gsresult != 0) {
  150         cerr << "Interpreter failure: " << gsresult << endl;
  151     }
  152     (void)CloseHandle(MyProcessInformation.hProcess);
  153     (void)CloseHandle(MyProcessInformation.hThread);
  154     return gsresult;
  155 }
  156 
  157 // define PSTOEDITDEBUG
  158 
  159 int callgs(int argc, const char * const argv[]) { 
  160     const bool verbose = false; // debug only
  161 
  162 //#define PSTOEDITDEBUG 1 
  163 #ifdef PSTOEDITDEBUG
  164     cerr << "Commandline " << endl;
  165     for (int i = 0; i < argc; i++) {
  166         cerr << "argv[" << i << "]: " << argv[i] << endl;
  167     }
  168 #endif
  169 
  170     /* force usage of exe - for test purposes only 
  171     char * dll = strstr(argv[0],"gsdll32.dll");
  172     strcpy(dll,"gswin32.exe");  
  173     */
  174 
  175     int result = false;
  176     // check the first arg in the command line whether it contains gsdll32.dll
  177     if ((strstr(argv[0],"gsdll32.dll") != nullptr) || (strstr(argv[0],"gsdll64.dll") != nullptr)) {
  178 #ifdef WITHDLLSUPPORT
  179          result = callgsDLL(argc, (char **) argv);
  180 #else
  181         cerr << "Sorry, but DLL support was not enabled in this version of pstoedit" << endl;
  182         return 2;
  183 #endif
  184     } else {
  185         result = callgsEXE(argc,argv); // callgsDLL(argc, (char **) argv);
  186     }
  187 
  188 
  189         if (result == -1 ) /* could not even load the dll/exe - so try fallback exe */
  190         { 
  191             const char * * newargv = new const char *[argc];
  192             for (int i = 0; i< argc; i++) { newargv[i] = argv[i]; }
  193 
  194             char * dlldirname = cppstrdup(argv[0]);
  195             char * p = strrchr(dlldirname, '\\'); 
  196             if (p) {
  197                 p++;
  198                 *p = 0; 
  199             }
  200             const RSString gsdir(dlldirname);
  201             delete[] dlldirname;
  202 
  203 #ifdef _WIN64
  204             const RSString defaultexe(gsdir + RSString("gswin64c.exe"));
  205             const RSString fallbackexe(gsdir + RSString("gswin32c.exe"));
  206 
  207 #else
  208             const RSString defaultexe(gsdir + RSString("gswin32c.exe"));
  209             const RSString fallbackexe(gsdir + RSString("gswin64c.exe"));
  210 #endif
  211             const RSString exename( fileExists(defaultexe.c_str()) ? defaultexe : fallbackexe );
  212             if (verbose) {
  213                 cerr << "loading: " << argv[0] << " failed (possibly due to 32/64 bit mix - reverting to call gs as exe via: " << exename << endl;
  214             }
  215             newargv[0] = exename.c_str();
  216             result = callgsEXE(argc,newargv);
  217             delete [] newargv; /* just the array - the content is not owned */ 
  218             return  result;
  219         } else return result;
  220 
  221 
  222 
  223 #if 0
  224     } else {
  225         if (verbose) {
  226             cerr << "calling gs as exe: " << argv[0] << endl;
  227         }
  228         return callgsEXE(argc,argv);
  229     }
  230 #endif
  231 
  232 }
  233 
  234 
  235 #else
  236 // not a windows system
  237 int callgs(int argc, const char *const argv[])
  238 {
  239 #ifndef USE_FORK
  240     RSString commandline = createCmdLine(argc, argv);
  241     commandline += " 1>&2" ; // redirect all stdout of Ghostscript to stderr
  242                              // in order not to interfere with stdout of pstoedit
  243     const int result = system(commandline.c_str());
  244     return result;
  245 #else
  246     //
  247     // version using fork as proposed by Guan Xin - but this does not handle stdout redirection.
  248     //
  249 
  250     /* Return values:
  251        -1:          error spawning gs
  252        -2:          error waiting gs
  253        otherwise:   exit status of gs
  254     */
  255 
  256     const int pid = fork();
  257     
  258     switch(pid)
  259     {
  260         case -1:
  261             perror("fork");
  262             return -1;
  263         case 0:
  264             execvp(argv[0], argv);
  265             perror("execvp");
  266             return -1;
  267         default:
  268         {
  269             int status;
  270             
  271             if(pid == waitpid(pid, &status, 0) && WIFEXITED(status))
  272             {
  273                 return WEXITSTATUS(status);
  274             }
  275             return -2;
  276         }
  277     }
  278 #endif
  279 
  280 }
  281 #endif
  282 
  283 #define str(x) #x
  284 #define xstr(x) str(x)
  285 
  286 
  287 const char *whichPI(ostream & errstream, int verbose, const char *gsregbase, const char * gsToUse)
  288 {
  289 // determines which PostScript interpreter to use
  290 // !FIXME: change the sequence to 2-1-3 (for Unix); with the upcoming gsview for X11 possibly introduce
  291 //         a lookup of "gsviewX11.ini" (or whatever its name is)
  292 // !FIXME: possibly introduce a new environment var. GS_DLL or the like 
  293 // WIN32:
  294     // 1. look in the registry
  295     // 2. look into gsview32.ini
  296     // 2. look in the environment for the value of GS -- NOT TRUE! This is commented out.
  297     // 4. look for the compiled-in DEFAULTGS (which has to hold the DLL)
  298 // OS/2:
  299     // 1. look in the native profile pstoedit.ini
  300     // 2. look into gvpm.ini
  301     // 3. look for the compiled-in DEFAULTGS (which has to hold the DLL)
  302 // else (i.e. UNIX):
  303     // 1. look in the environment for the value of GS
  304     // 2. look in the "registry" ($(HOME)/.pstoedit.reg)
  305     // 3. look for the compiled-in DEFAULTGS (which has to hold the executable)
  306 #ifdef DEFAULTGS
  307     static const char *const defaultgs = xstr(DEFAULTGS);
  308 #else
  309     static const char *const defaultgs = "";
  310 #endif
  311     const char *gstocall = nullptr;
  312 
  313     // for debugging verbose = true; 
  314     if (verbose)
  315             errstream << endl << "Looking up where to find the PostScript interpreter." << endl;
  316 
  317     if ((gsToUse != nullptr) && !strequal(gsToUse,"") ) {
  318         if (verbose) {
  319             errstream << " an explicit path was given - using : " << gsToUse << endl;
  320         }
  321         // an explicit path is given as option already - this overrules everthing
  322         return gsToUse;
  323     }
  324 #if defined (_WIN32)
  325 
  326     RSString gstocallfromregistry = getRegistryValue(errstream, "common", "gstocall");
  327     if (gstocallfromregistry.length()) {
  328         if (verbose)
  329             errstream << "found value in registry" << endl;
  330         static char buffer[2000];
  331         buffer[2000-1] = 0; // add EOS
  332         strncpy_s(buffer,2000-1, gstocallfromregistry.c_str(),2000-1);
  333         //  delete[]gstocallfromregistry;
  334         gstocall = buffer;
  335     } else {
  336         if (verbose)
  337             errstream << "didn't find value in registry, trying gsview32.ini" << endl;
  338         // try gsview32.ini
  339         static char pathname[1000]; // static, since we return it
  340         const char inifilename[] = "gsview32.ini";
  341 #ifdef WITHGETINI
  342         char fullinifilename[1000];
  343         getini(verbose, errstream, fullinifilename, inifilename, sizeof(fullinifilename));
  344 #else
  345         const char *fullinifilename = inifilename;
  346 #endif
  347         if (verbose)
  348             errstream << "looking in " << fullinifilename << endl;
  349         const DWORD result = GetPrivateProfileString("Options",
  350                                                "GhostscriptDLL",
  351                                                "",  //default
  352                                                pathname,
  353                                                sizeof(pathname),
  354                                                fullinifilename);
  355         if (result > 0) {
  356             if (verbose) {
  357                 errstream << "found value in ";
  358                 if (strcmp(inifilename, fullinifilename) == 0) {
  359                     char sysdir[2000];
  360                     sysdir[0] = '\0';
  361                     const UINT ret = GetWindowsDirectory(sysdir, 2000);
  362                     if (ret)
  363                         errstream << sysdir << '\\';
  364                 }
  365                 errstream << fullinifilename << endl;
  366             }
  367             gstocall = pathname;
  368         } else {
  369             if (verbose) {
  370                 errstream<< "nothing found in gsview32.ini file - using find_gs to lookup latest version of Ghostscript in registry " << endl;
  371                 (void)dumpgsvers(gsregbase, verbose);
  372             }
  373             static char buf[1000];
  374             if (find_gs(buf, sizeof(buf), 550 /* min ver*/ , getPstoeditsetDLLUsage() , gsregbase, verbose)) { 
  375                 if (verbose) {
  376                     if (getPstoeditsetDLLUsage()) errstream << "Latest GS DLL is " << buf << endl;
  377                     else        errstream << "Latest GS EXE is " << buf << endl;
  378                 }
  379                 gstocall = buf;
  380             } else {
  381                 if (verbose)
  382                     errstream << "find_gs couldn't find GS in registry" << endl;
  383                 if (strlen(defaultgs) > 0) {
  384                     gstocall = defaultgs;
  385                 } else {
  386                     errstream <<
  387                         "Fatal: don't know which interpreter to call. " <<
  388                         "Either enter gstocall into the registry " <<
  389                         "or compile again with -DDEFAULTGS=..." << endl;
  390                     gstocall = nullptr;
  391                 }
  392             }
  393         }
  394     }
  395 #elif defined (__OS2__)
  396     unused(&gsregbase);
  397     RSString gstocallfromregistry = getRegistryValue(errstream, "common", "gstocall");
  398     if (gstocallfromregistry.length() ) {
  399         if (verbose)
  400             errstream << "found value in pstoedit.ini" << endl;
  401         static char buffer[2000];
  402         buffer[2000-1] = 0; // add EOS
  403         strncpy(buffer, gstocallfromregistry.c_str(),2000-1);
  404         gstocall = buffer;
  405     } else {
  406         if (verbose)
  407             errstream << "didn't find value in pstoedit.ini, trying gvpm.ini" << endl;
  408         // try gvpm.ini
  409         static char pathname[1000]; // static, since we return it
  410         const char inifilename[] = "gvpm.ini";
  411 #ifdef WITHGETINI
  412         char fullinifilename[1000];
  413         getini(verbose, errstream, fullinifilename, inifilename, sizeof(fullinifilename));
  414 #else
  415         const char *fullinifilename = inifilename;
  416 #endif
  417         if (verbose)
  418             errstream << "looking in " << fullinifilename << endl;
  419         ifstream regfile(fullinifilename);
  420         int result = 0;
  421         if (regfile) {
  422             char line[1000];
  423             while (!regfile.eof() && !result) {
  424                 regfile.getline(line, 1000);
  425                 if (strstr(line, "[Options]"))
  426                     do {
  427                         regfile.getline(line, 1000);
  428                         if (strstr(line, "GhostscriptDLL=")) {
  429                             strncpy(pathname, line + strlen("GhostscriptDLL="),1000);
  430                             char *cr = strrchr(pathname, '\r');
  431                             if (cr)
  432                                 *cr = 0;
  433                             result = 1;
  434                             break;
  435                         }
  436                     }
  437                     while (!regfile.eof() && !strchr(line, '['));
  438             }
  439         }
  440         if (result > 0) {
  441             if (verbose)
  442                 errstream << "found value in " << fullinifilename << endl;
  443             gstocall = pathname;
  444         } else {
  445 
  446             if (strlen(defaultgs) > 0) {    
  447                 gstocall = defaultgs;
  448                 if (verbose)
  449                     errstream << "nothing found so far, trying default: " << defaultgs << endl;
  450             } else {
  451                 errstream <<
  452                     "Fatal: don't know which interpreter to call. " <<
  453                     "Either enter gstocall into pstoedit.ini " <<
  454                     " or compile again with -DDEFAULTGS=..." << endl;
  455                 gstocall = 0;
  456             }
  457         }
  458     }
  459 #else                           //UNIX
  460     unused(&gsregbase);
  461     gstocall = getenv("GS");
  462     if (gstocall == nullptr) {
  463         if (verbose)
  464             errstream << "GS not set, trying registry for common/gstocall" << endl;
  465         RSString gstocallfromregistry = getRegistryValue(errstream, "common", "gstocall");
  466         if (gstocallfromregistry.length()) {
  467             if (verbose)
  468                 errstream << "found value in registry" << endl;
  469             static char buffer[2000];
  470             buffer[2000-1] = 0; // add EOS
  471             strncpy(buffer, gstocallfromregistry.c_str(),2000-1);
  472             gstocall = buffer;
  473         } else {
  474             {
  475 
  476                 if (strlen(defaultgs) > 0) {
  477                     gstocall = defaultgs;
  478                     if (verbose)
  479                         errstream << "nothing found so far, trying default: " << defaultgs << endl;
  480                 } else {
  481                     errstream <<
  482                         "Fatal: don't know which interpreter to call. " <<
  483                         "Either setenv GS or compile again with -DDEFAULTGS=..." << endl;
  484                     gstocall = nullptr;
  485                 }
  486             }
  487         }
  488     } else {
  489         if (verbose)
  490             errstream << "GS is set to:" << gstocall << endl;
  491     }
  492 #endif
  493     if (verbose && gstocall&& !strequal(gstocall,""))
  494         errstream << "Value found is:" << gstocall << endl;
  495     return gstocall;
  496 }
  497 
  498 
  499 #if defined(_WIN32)
  500 static const char *getOSspecificOptions(int verbose, ostream & errstream, char *buffer, unsigned int   buflen   )
  501 {
  502     const char *PIOptions = nullptr;
  503     if (verbose)
  504         errstream << "didn't find value in registry, trying gsview32.ini" << endl;
  505     // try gsview32.ini
  506     const char inifilename[] = "gsview32.ini";
  507 #ifdef WITHGETINI
  508     char fullinifilename[1000];
  509     getini(verbose, errstream, fullinifilename, inifilename, sizeof(fullinifilename));
  510 #else
  511     const char *fullinifilename = inifilename;
  512 #endif
  513     if (verbose)
  514         errstream << "looking in " << fullinifilename << endl;
  515     const DWORD result = GetPrivateProfileString("Options",
  516                                            "GhostscriptInclude",
  517                                            "",  //default
  518                                            buffer,
  519                                            buflen,
  520                                            fullinifilename);
  521     if (result > 0) {           //2.
  522         if (verbose) {
  523             errstream << "found value in ";
  524             if (strcmp(inifilename, fullinifilename) == 0) {
  525                 char sysdir[2000];
  526                 sysdir[0] = '\0';
  527                 const UINT ret = GetWindowsDirectory(sysdir, 2000);
  528                 if (ret)
  529                     errstream << sysdir << '\\';
  530             }
  531             errstream << fullinifilename << endl;
  532         }
  533         PIOptions = buffer;
  534     } else {
  535         // 3.
  536 #if 0
  537         // no longer needed with newest find_gs. gs stores the related gs_lib in the registry.
  538         static char buf[500];
  539         const unsigned int gsver = get_latest_gs_version();
  540         if (gsver) {
  541             get_gs_string(gsver, "GS_LIB", buf, sizeof(buf));
  542             if (verbose) {
  543                 errstream << "found GS_LIB as " << buf << " from latest version of gs" << endl;
  544             }
  545             PIOptions = buf;
  546         }
  547 #endif
  548 
  549     }
  550     return PIOptions;
  551 }
  552 
  553 static const char * const lookupplace = "registry";
  554 
  555 #elif defined(__OS2__)
  556 static const char *getOSspecificOptions(int verbose, ostream & errstream, char *buffer, unsigned int buflen)
  557 {
  558     const char *PIOptions = 0;
  559     if (verbose)
  560         errstream << "didn't find value in pstoedit.ini, trying gvpm.ini" << endl;
  561     // try gvpm.ini
  562     const char inifilename[] = "gvpm.ini";
  563     char fullinifilename[1000];
  564     getini(verbose, errstream, fullinifilename, inifilename, sizeof(fullinifilename));
  565     if (verbose)
  566         errstream << "looking in " << fullinifilename << endl;
  567     ifstream regfile(fullinifilename);
  568     int result = 0;
  569     if (regfile) {
  570         char line[1000];
  571         while (!regfile.eof() && !result) {
  572             regfile.getline(line, 1000);
  573             if (strstr(line, "[Options]"))
  574                 do {
  575                     regfile.getline(line, 1000);
  576                     if (strstr(line, "GhostscriptInclude=")) {
  577                         strncpy(buffer, line + strlen("GhostscriptInclude="),buflen);
  578                         char *cr = strrchr(buffer, '\r');
  579                         if (cr)
  580                             *cr = 0;
  581                         result = 1;
  582                         break;
  583                     }
  584                 }
  585                 while (!regfile.eof() && !strchr(line, '['));
  586         }
  587     }
  588     if (result > 0) {           //2.
  589         if (verbose) {
  590             errstream << "found value in " << fullinifilename << endl;
  591         }
  592         PIOptions = buffer;
  593     }
  594     return PIOptions;
  595 
  596 }
  597 static const char * const lookupplace = "pstoedit.ini";
  598 #else
  599 static const char *getOSspecificOptions(int verbose, ostream & errstream, char *buffer, unsigned int buflen)
  600 {
  601     unused(&verbose); unused(&errstream); unused(buffer); unused(&buflen);
  602     return nullptr;
  603 }
  604 static const char * const lookupplace = "registry";
  605 #endif
  606 
  607 
  608 const char *defaultPIoptions(ostream & errstream, int verbose)
  609 {
  610     // returns default options to be passed to the Postscript Interpreter
  611     // WIN32:
  612     // 1. look in the registry
  613     // 2. look into gsview32.ini
  614     // 3. look for latest version of Ghostscript in registry
  615     // 4. look in the environment for the value of GS_LIB
  616     // 5. look for the compiled-in GS_LIB
  617     // OS/2:
  618     // 1. look in the native profile pstoedit.ini
  619     // 2. look into gvpm.ini
  620     // 3. look in the environment for the value of GS_LIB
  621     // 4. look for the compiled-in GS_LIB
  622     // else (i.e. UNIX):
  623     // 1. look in the "registry" ($(HOME)/.pstoedit.reg)
  624     // 2. look in the environment for the value of GS_LIB
  625     // 3. look for the compiled-in GS_LIB
  626 
  627 #ifdef GS_LIB
  628     static const char *const defaultPIOptions = xstr(GS_LIB);
  629 #else
  630     static const char *const defaultPIOptions = "";
  631 #endif
  632     static char buffer[2000];
  633     const char *PIOptions;
  634     if (verbose)
  635         errstream << endl << "Looking up specific options for the PostScript interpreter." << endl << "First trying " << lookupplace << " for common/GS_LIB" << endl;
  636 
  637     // try first registry/ini value, then GS_LIB and at last the default
  638     RSString PIOptionsfromregistry = getRegistryValue(errstream, "common", "GS_LIB");
  639     if (PIOptionsfromregistry.length()) {   // 1.
  640         if (verbose)
  641             errstream << "found value in " << lookupplace << endl;
  642         strncpy_s(buffer,sizeof(buffer), PIOptionsfromregistry.c_str(),sizeof(buffer));
  643         // delete[]PIOptionsfromregistry;
  644         PIOptions = buffer;
  645     } else {                    //2.-4.
  646 
  647         PIOptions = getOSspecificOptions(verbose, errstream, buffer,sizeof(buffer) );
  648 
  649         if (PIOptions == nullptr) { //3.
  650             if (verbose)
  651                 errstream << "still not found an entry - now trying GS_LIB env var." << endl;
  652             PIOptions = getenv("GS_LIB");
  653             if (PIOptions == nullptr) { //4.
  654                 if (verbose) errstream << "GS_LIB not set" << endl;
  655                 if (strlen(defaultPIOptions) > 0) {
  656                     PIOptions = defaultPIOptions;
  657                     if (verbose) errstream << "nothing found so far, trying default: " << defaultPIOptions<< endl;
  658                 } else {
  659                     PIOptions = nullptr;
  660                 }
  661             } else { 
  662                 if (verbose)
  663                     errstream << "GS_LIB is set to:" << PIOptions << endl;
  664             }
  665         }
  666     }
  667 
  668     if (PIOptions && (PIOptions[0] != '-') && (PIOptions[1] != 'I')) {
  669         static char returnbuffer[2000];
  670         returnbuffer[2000-1]=0;
  671         strncpy_s(returnbuffer,sizeof(returnbuffer)-1, "-I",sizeof(returnbuffer)-1);
  672         strcat_s(returnbuffer,sizeof(returnbuffer)-1, PIOptions);
  673         PIOptions = returnbuffer;
  674     }
  675     if (verbose )
  676         errstream << "Value returned:" << (PIOptions ? PIOptions : "") << endl << endl;
  677     return PIOptions;
  678 }
  679 
  680 const char *whichPINoVerbose(ostream & errstream, const char *gsregbase, const char * gsToUse)
  681 {
  682     return whichPI(errstream, 0, gsregbase, gsToUse);
  683 }