home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / historic / v92.tgz / v92.tar / v92 / src / preproc / files.c < prev    next >
C/C++ Source or Header  |  1996-03-22  |  20KB  |  813 lines

  1. /*
  2.  * This file contains routines for setting up characters sources from
  3.  *  files. It contains code to handle the search for include files.
  4.  */
  5. #include "::preproc:preproc.h"
  6. /*
  7.  * The following code is operating-system dependent [@files.01].
  8.  *  System header files needed for handling paths.
  9.  */
  10.  
  11. #if PORT
  12.    /* something may be needed */
  13. Deliberate Syntax Error
  14. #endif                    /* PORT */
  15.  
  16. #if AMIGA || ATARI_ST || VM || MVS
  17.    /* something may be needed */
  18. Deliberate Syntax Error
  19. #endif                    /* AMIGA || ATARI_ST || ... */
  20.  
  21. #if MACINTOSH
  22. #include <stdio.h>
  23. char *FileNameMacToUnix(char *fn);
  24. char *FileNameUnixToMac(char *fn);
  25. char *FileNameMacConvert(char *(*func)(char *),char *fn);
  26. #endif                    /* MACINTOSH */
  27.  
  28. #if MSDOS
  29. #if MICROSOFT || INTEL_386 || HIGHC_386 || ZTC_386 || WATCOM
  30.    /* nothing is needed */
  31. #endif                    /* MICROSOFT || INTEL_386 || ... */
  32. #if TURBO || BORLAND_286 || BORLAND_386
  33. #include <dir.h>
  34. #endif                     /* TURBO || BORLAND_286 ... */
  35. #endif                    /* MSDOS */
  36.  
  37. #if UNIX || VMS
  38.    /* nothing is needed */
  39. #endif                    /* UNIX || VMS */
  40.  
  41. /*
  42.  * End of operating-system specific code.
  43.  */
  44.  
  45. #include "::preproc:pproto.h"
  46.  
  47. /*
  48.  * Prototype for static function.
  49.  */
  50. hidden novalue file_src Params((char *fname, FILE *f));
  51.  
  52. static char **incl_search; /* standard locations to search for header files */
  53.  
  54. /*
  55.  * file_src - set up the structures for a characters source from a file,
  56.  *  putting the source on the top of the stack.
  57.  */
  58. static novalue file_src(fname, f)
  59. char *fname;
  60. FILE *f;
  61.    {
  62.    union src_ref ref;
  63.  
  64. /*
  65.  * The following code is operating-system dependent [@files.02].
  66.  *  Insure that path syntax is in Unix format for internal consistency
  67.  *  (note, this may not work well on all systems).
  68.  */
  69.  
  70. #if PORT
  71.    /* something may be needed */
  72. Deliberate Syntax Error
  73. #endif                    /* PORT */
  74.  
  75. #if AMIGA || ATARI_ST || VM || MVS
  76.    /* something may be needed */
  77. Deliberate Syntax Error
  78. #endif                    /* AMIGA || ATARI_ST || ... */
  79.  
  80. #if MACINTOSH
  81.    fname = FileNameMacConvert(FileNameMacToUnix,fname);
  82. #endif                    /* MACINTOSH */
  83.  
  84. #if MSDOS
  85.    char *s;
  86.    
  87.    /*
  88.     * Convert back slashes to slashes for internal consistency.
  89.     */
  90.    fname = (char *)strdup(fname);
  91.    for (s = fname; *s != '\0'; ++s)
  92.       if (*s == '\\')
  93.          *s = '/';
  94. #endif                    /* MSDOS */
  95.  
  96. #if UNIX || VMS
  97.    /* nothing is needed */
  98. #endif                    /* UNIX || VMS */
  99.  
  100. /*
  101.  * End of operating-system specific code.
  102.  */
  103.  
  104.    ref.cs = new_cs(fname, f, CBufSize);
  105.    push_src(CharSrc, &ref);
  106.    next_char = NULL;
  107.    fill_cbuf();
  108.    }
  109.  
  110. /*
  111.  * source - Open the file named fname or use stdin if fname is "-". fname
  112.  *  is the first file from which to read input (that is, the outermost file).
  113.  */
  114. novalue source(fname)
  115. char *fname;
  116.    {
  117.    FILE *f;
  118.  
  119.    if (strcmp(fname, "-") == 0)
  120.       file_src("<stdin>", stdin);
  121.    else {
  122.       if ((f = fopen(fname, "r")) == NULL) 
  123.          err2("cannot open ", fname);
  124.       file_src(fname, f);
  125.       }
  126.    }
  127.  
  128. /*
  129.  * include - open the file named fname and make it the current input file. 
  130.  */
  131. novalue include(trigger, fname, system)
  132. struct token *trigger;
  133. char *fname;
  134. int system;
  135.    {
  136.    struct str_buf *sbuf;
  137.    char *s;
  138.    char *path;
  139.    char *end_prfx;
  140.    struct src *sp;
  141.    struct char_src *cs;
  142.    char **prefix;
  143.    FILE *f;
  144.  
  145.    /*
  146.     * See if this is an absolute path name.
  147.     */
  148.    if (fname[0] != '/') {
  149.       sbuf = get_sbuf();
  150. #if  !MVS && !VM                    /* ??? */
  151.       f = NULL;
  152.       if (!system) {
  153.          /*
  154.           * This is not a system include file, so search the locations
  155.           *  of the "ancestor files".
  156.           */
  157.          sp = src_stack;
  158.          while (f == NULL && sp != NULL) {
  159.             if (sp->flag == CharSrc) {
  160.                cs = sp->u.cs;
  161.                if (cs->f != NULL) {
  162.                   /*
  163.                    * This character source is a file.
  164.                    */
  165.                   end_prfx = NULL;
  166.                   for (s = cs->fname; *s != '\0'; ++s)
  167.                      if (*s == '/')
  168.                         end_prfx = s;
  169.                   if (end_prfx != NULL) 
  170. #if MACINTOSH
  171.              /*
  172.               * For Mac-style names, don't include the file
  173.               * separator character in the prefix.
  174.               */
  175.                      for (s = cs->fname; s < end_prfx; ++s)
  176. #else                    /* MACINTOSH */
  177.                      for (s = cs->fname; s <= end_prfx; ++s)
  178. #endif                    /* MACINTOSH */
  179.                         AppChar(*sbuf, *s);
  180.                   for (s = fname; *s != '\0'; ++s)
  181.                      AppChar(*sbuf, *s);
  182.                   path = str_install(sbuf);
  183. #if MACINTOSH
  184.           /*
  185.            * Convert UNIX-style path to Mac-style.
  186.            */
  187.           path = FileNameMacConvert(FileNameUnixToMac,path);
  188. #endif                    /* MACINTOSH */
  189.                   f = fopen(path, "r");
  190.                   }
  191.                }
  192.             sp = sp->next;
  193.             }
  194.          }
  195.       /*
  196.        * Search in the locations for the system include files.
  197.        */   
  198.       prefix = incl_search;
  199.       while (f == NULL && *prefix != NULL) {
  200.          for (s = *prefix; *s != '\0'; ++s)
  201.             AppChar(*sbuf, *s);
  202.          if (s > *prefix && s[-1] != '/')
  203.             AppChar(*sbuf, '/');
  204.          for (s = fname; *s != '\0'; ++s)
  205.             AppChar(*sbuf, *s);
  206.          path = str_install(sbuf);
  207. #if MACINTOSH
  208.      /*
  209.       * Convert UNIX-style path to Mac-style.
  210.       */
  211.      path = FileNameMacConvert(FileNameUnixToMac,path);
  212. #endif                    /* MACINTOSH */
  213.          f = fopen(path, "r");
  214.          prefix = ++prefix;
  215.          }
  216.       rel_sbuf(sbuf);
  217. #else                    /* !MVS && !VM */
  218.       if (system) {
  219.          for (s = "ddn:SYSLIB("; *s != '\0'; ++s)
  220.             AppChar(*sbuf, *s);
  221.          for (s = fname; *s != '\0' && *s != '.'; ++s)
  222.             AppChar(*sbuf, *s);
  223.          AppChar(*sbuf, ')');
  224.          }
  225.       else {
  226.          char *t;
  227.          for (s = "ddn:"; *s != '\0'; ++s)
  228.             AppChar(*sbuf, *s);
  229.          t = fname;
  230.          do {
  231.             for (s = t; *s != '/' && *s != '\0'; ++s);
  232.             if (*s != '\0') t = s+1;
  233.             } while (*s != '\0');
  234.          for (s = t; *s != '.' && *s != '\0'; ++s);
  235.          if (*s == '\0') {
  236.             AppChar(*sbuf, 'H');
  237.             }
  238.          else for (++s; *s != '\0'; ++s)
  239.             AppChar(*sbuf, *s);
  240.          AppChar(*sbuf, '(');
  241.          for (; *t != '.' && *t != '\0'; ++t)
  242.             AppChar(*sbuf, *t);
  243.          AppChar(*sbuf, ')');
  244.          }
  245.       path = str_install(sbuf);
  246.       f = fopen(path, "r");
  247.       rel_sbuf(sbuf);
  248. #endif                    /* !MVS && !VM */
  249.       }
  250.    else {
  251.       path = fname;
  252.       f = fopen(path, "r");
  253.       }
  254.  
  255.    if (f == NULL)
  256.       errt2(trigger, "cannot open include file ", fname);
  257.    file_src(path, f);
  258.    }
  259.  
  260. /*
  261.  * init_files - Initialize this module, setting up the search path for
  262.  *  system header files.
  263.  */
  264. novalue init_files(opt_lst, opt_args)
  265. char *opt_lst;
  266. char **opt_args;
  267.    {
  268.    int n_paths = 0;
  269.    int i, j;
  270.    char *s, *s1;
  271.   
  272. /*
  273.  * The following code is operating-system dependent [@files.03].
  274.  *  Determine the number of standard locations to search for
  275.  *  header files and provide any declarations needed for the code
  276.  *  that establishes these search locations.
  277.  */
  278.  
  279. #if PORT
  280.    /* probably needs something */
  281. Deliberate Syntax Error
  282. #endif                    /* PORT */
  283.  
  284. #if VMS
  285.    char **syspaths;
  286.    int  vmsi;
  287.  
  288.    n_paths = vmsi = 0;
  289.    syspaths = (char **)alloc((unsigned int)(sizeof(char *) * 2));
  290.    if (syspaths[n_paths] = getenv("VAXC$INCLUDE")) {
  291.       n_paths++;
  292.       vmsi++;
  293.       }
  294.    if (syspaths[n_paths] = getenv("SYS$LIBRARY")) {
  295.       n_paths++;
  296.       vmsi++;
  297.       }
  298. #endif                    /* VMS */
  299.  
  300. #if AMIGA || ATARI_ST || VM || MVS || (MACINTOSH && !MPW && !THINK_C)
  301.    /* probably needs something */
  302. Deliberate Syntax Error
  303. #endif                    /* AMIGA || ATARI_ST || ... */
  304.  
  305. #if MACINTOSH
  306. #if THINK_C
  307.    char *sysdir = FileNameMacConvert(FileNameMacToUnix, "MacintoshHD:THINK C:THINK C:Standard Libraries:C headers");
  308.    n_paths = 1;
  309. #endif
  310. #if MPW
  311.    /*
  312.     * For MPW, environment variable CIncludes says where to look.
  313.     */
  314.    char *sysdir = FileNameMacConvert(FileNameMacToUnix,getenv("CIncludes"));
  315.    n_paths = 1;
  316. #endif                    /* MPW */
  317. #endif                    /* MACINTOSH */
  318.  
  319. #if MSDOS
  320. #if HIGHC_386 || INTEL_386 || WATCOM
  321.    /* punt for now */
  322.    n_paths = 0;
  323. #endif                    /* HIGHC_386 || INTEL_386 || ... */
  324.  
  325. #if MICROSOFT || NT
  326.    char *syspath;
  327.    char *cl_var;
  328.    char *incl_var;
  329.    
  330.    incl_var = getenv("INCLUDE");
  331.    cl_var = getenv("CL");
  332.    n_paths = 0;
  333.  
  334.    /*
  335.     * Check the CL environment variable for -I and -X options.
  336.     */
  337.    if (cl_var != NULL) {
  338.       s = cl_var;
  339.       while (*s != '\0') {
  340.          if (*s == '/' || *s == '-') {
  341.             ++s;
  342.             if (*s == 'I') {
  343.                ++n_paths;
  344.                ++s;
  345.                while (*s == ' ' || *s == '\t')
  346.                   ++s;
  347.                while (*s != ' ' && *s != '\t' && *s != '\0')
  348.                   ++s;
  349.                }
  350.             else if (*s == 'X')
  351.                incl_var = NULL;        /* ignore INCLUDE environment var */
  352.             }
  353.          if (*s != '\0')
  354.             ++s;
  355.          }
  356.       }
  357.  
  358.    /*
  359.     * Check the INCLUDE environment variable for standard places to
  360.     *  search.
  361.     */
  362.    if (incl_var == NULL)
  363.       syspath = "";
  364.    else {
  365.       syspath = (char *)strdup(incl_var);
  366.       if (*incl_var != '\0')
  367.          ++n_paths;
  368.       while (*incl_var != '\0')
  369.          if (*incl_var++ == ';' && *incl_var != '\0')
  370.             ++n_paths;
  371.       }
  372. #endif                    /* MICROSOFT || NT */
  373.  
  374. #if ZTC_386
  375.    char *syspath;
  376.    char *cl_var;
  377.    char *incl_var;
  378.    
  379.    incl_var = getenv("INCLUDE");
  380.    cl_var = getenv("CFLAGS");
  381.    n_paths = 0;
  382.  
  383.    /*
  384.     * Check the CFLAGS environment variable for -I options.
  385.     */
  386.    if (cl_var != NULL) {
  387.       s = cl_var;
  388.       while (*s != '\0') {
  389.          if (*s == '/' || *s == '-') {
  390.             ++s;
  391.             if (*s == 'I') {
  392.                ++n_paths;
  393.                ++s;
  394.                while (*s == ' ' || *s == '\t')
  395.                   ++s;
  396.                while (*s != ' ' && *s != '\t' && *s != '\0') {
  397.                   if (*s == ';')
  398.                       ++n_paths;
  399.                   ++s;
  400.                   }
  401.                }
  402.             }
  403.          if (*s != '\0')
  404.             ++s;
  405.          }
  406.       }
  407.  
  408.    /*
  409.     * Check the INCLUDE environment variable for standard places to
  410.     *  search.
  411.     */
  412.    if (incl_var == NULL)
  413.       syspath = "";
  414.    else {
  415.       syspath = (char *)strdup(incl_var);
  416.       if (*incl_var != '\0')
  417.          ++n_paths;
  418.       while (*incl_var != '\0')
  419.          if (*incl_var++ == ';' && *incl_var != '\0')
  420.             ++n_paths;
  421.       }
  422. #endif                    /* ZTC_386 */
  423.  
  424. #if TURBO || BORLAND_286 || BORLAND_386
  425.     char *cfg_fname;
  426.     FILE *cfg_file = NULL;
  427.     struct str_buf *sbuf;
  428.     int c;
  429.  
  430.     /*
  431.      * Check the configuration files for -I options.
  432.      */
  433.     n_paths = 0;
  434.     cfg_fname = searchpath("turboc.cfg");
  435.     if (cfg_fname != NULL && (cfg_file = fopen(cfg_fname, "r")) != NULL) {
  436.        c = getc(cfg_file);
  437.        while (c != EOF) {
  438.           if (c == '-') {
  439.              if ((c = getc(cfg_file)) == 'I')
  440.                 ++n_paths;
  441.              }
  442.           else
  443.              c = getc(cfg_file);
  444.           }
  445.        }
  446. #endif                     /* TURBO || BORLAND_286 ... */
  447.  
  448. #if HIGHC_386 || INTEL_386 || WATCOM
  449.    /* something may be needed */
  450. #endif                    /* HIGHC_386 || INTEL_386 || ... */
  451. #endif                    /* MSDOS */
  452.  
  453. #if UNIX
  454.    static char *sysdir = "/usr/include/";
  455.  
  456.    n_paths = 1;
  457. #endif                    /* UNIX */
  458.  
  459. /*
  460.  * End of operating-system specific code.
  461.  */
  462.  
  463.    /*
  464.     * Count the number of -I options to the preprocessor.
  465.     */
  466.    for (i = 0; opt_lst[i] != '\0'; ++i)
  467.       if (opt_lst[i] == 'I')
  468.          ++n_paths;
  469.  
  470.    /*
  471.     * Set up the array of standard locations to search for header files.
  472.     */
  473.    incl_search = (char **)alloc((unsigned int)(sizeof(char *)*(n_paths + 1)));
  474.    j = 0;
  475.   
  476. /*
  477.  * The following code is operating-system dependent [@files.04].
  478.  *  Establish the standard locations to search before the -I options
  479.  *  on the preprocessor.
  480.  */
  481.  
  482. #if PORT
  483.    /* something may be needed */
  484. Deliberate Syntax Error
  485. #endif                    /* PORT */
  486.  
  487. #if AMIGA || ATARI_ST || VM || MVS
  488.    /* something may be needed */
  489. Deliberate Syntax Error
  490. #endif                    /* AMIGA || ATARI_ST || ... */
  491.  
  492. #if MSDOS
  493. #if MICROSOFT
  494.    /*
  495.     * Get locations from -I options from the CL environment variable.
  496.     */
  497.    if (cl_var != NULL)
  498.       while (*cl_var != '\0') {
  499.          if (*cl_var == '/' || *cl_var == '-') {
  500.             ++cl_var;
  501.             if (*cl_var == 'I') {
  502.                   ++cl_var;
  503.                   while (*cl_var == ' ' || *cl_var == '\t')
  504.                      ++cl_var;
  505.                   i = 0;
  506.                   while (cl_var[i] != ' ' && cl_var[i] != '\t' &&
  507.                     cl_var[i] != '\0')
  508.                      ++i;
  509.                   s1 = (char *) alloc((unsigned int)(i + 1));
  510.                   strncpy(s1, cl_var, i);
  511.                   s1[i] = '\0';
  512.                   /*
  513.                    * Convert back slashes to slashes for internal consistency.
  514.                    */
  515.                   for (s = s1; *s != '\0'; ++s)
  516.                      if (*s == '\\')
  517.                         *s = '/';
  518.                   incl_search[j++] = s1;
  519.                   cl_var += i;
  520.                }
  521.             }
  522.          if (*cl_var != '\0')
  523.             ++cl_var;
  524.          }
  525. #endif                    /* MICROSOFT */
  526.  
  527. #if ZTC_386
  528.    /*
  529.     * Get locations from -I options from the CL environment variable.
  530.     * Each -I may have multiple options separated by semi-colons.
  531.     */
  532.    if (cl_var != NULL)
  533.       while (*cl_var != '\0') {
  534.          if (*cl_var == '/' || *cl_var == '-') {
  535.             ++cl_var;
  536.             if (*cl_var == 'I') {
  537.                   ++cl_var;
  538.                   while (*cl_var == ' ' || *cl_var == '\t')
  539.                      ++cl_var;
  540.                   i = 0;
  541.                   while (cl_var[i] != ' ' && cl_var[i] != '\t' &&
  542.                     cl_var[i] != '\0') {
  543.                      while (cl_var[i] != ' ' && cl_var[i] != '\t' &&
  544.                        cl_var[i] != ';' && cl_var[i] != '\0')
  545.                         ++i;
  546.                      s1 = (char *) alloc((unsigned int)(i + 1));
  547.                      strncpy(s1, cl_var, i);
  548.                      s1[i] = '\0';
  549.                      /*
  550.                       * Convert back slashes to slashes for internal consistency.
  551.                       */
  552.                      for (s = s1; *s != '\0'; ++s)
  553.                         if (*s == '\\')
  554.                            *s = '/';
  555.                      incl_search[j++] = s1;
  556.                      if (cl_var[i] == ';') {
  557.                          cl_var += (i + 1);
  558.                          i = 0;
  559.                          }
  560.                      }
  561.                   cl_var += i;
  562.                }
  563.             }
  564.          if (*cl_var != '\0')
  565.             ++cl_var;
  566.          }
  567. #endif                    /* ZTC_386 */
  568.  
  569. #if HIGHC_386 || INTEL_386 || WATCOM
  570.    /* something is needed */
  571. #endif                    /* HIGHC_386 || INTEL_386 || ... */
  572. #endif                    /* MSDOS */
  573.  
  574. #if UNIX || VMS || MACINTOSH
  575.    /* nothing is needed */
  576. #endif                    /* UNIX || VMS || MACINTOSH */
  577.  
  578. /*
  579.  * End of operating-system specific code.
  580.  */
  581.  
  582.    /*
  583.     * Get the locations from the -I options to the preprocessor.
  584.     */
  585.    for (i = 0; opt_lst[i] != '\0'; ++i)
  586.       if (opt_lst[i] == 'I') {
  587.          s = opt_args[i];
  588.          s1 = (char *) alloc((unsigned int)(strlen(s)+1));
  589.          strcpy(s1, s);
  590.          
  591. /*
  592.  * The following code is operating-system dependent [@files.05].
  593.  *  Insure that path syntax is in Unix format for internal consistency
  594.  *  (note, this may not work well on all systems).
  595.  */
  596.  
  597. #if PORT
  598.    /* something might be needed */
  599. Deliberate Syntax Error
  600. #endif                    /* PORT */
  601.  
  602. #if AMIGA || ATARI_ST || VM || MVS
  603.    /* something might be needed */
  604. Deliberate Syntax Error
  605. #endif                    /* AMIGA || ATARI_ST || ... */
  606.  
  607. #if MACINTOSH
  608.    s1 = FileNameMacConvert(FileNameMacToUnix,s);
  609. #endif                    /* MACINTOSH */
  610.  
  611. #if MSDOS
  612.          /*
  613.           * Convert back slashes to slashes for internal consistency.
  614.           */
  615.          for (s = s1; *s != '\0'; ++s)
  616.             if (*s == '\\')
  617.                *s = '/';
  618. #endif                    /* MSDOS */
  619.  
  620. #if UNIX || VMS
  621.    /* nothing is needed */
  622. #endif                    /* UNIX || VMS */
  623.  
  624. /*
  625.  * End of operating-system specific code.
  626.  */
  627.          
  628.          incl_search[j++] = s1;
  629.          }
  630.  
  631. /*
  632.  * The following code is operating-system dependent [@files.06].
  633.  *  Establish the standard locations to search after the -I options
  634.  *  on the preprocessor.
  635.  */
  636.  
  637. #if PORT
  638.    /* probably needs something */
  639. Deliberate Syntax Error
  640. #endif                    /* PORT */
  641.  
  642. #if VMS
  643.    for ( ; vmsi; vmsi--)
  644.       incl_search[n_paths - vmsi] = syspaths[vmsi-1];
  645. #endif                    /* VMS */
  646.  
  647. #if AMIGA || ATARI_ST || VM || MVS
  648.    /* probably needs something */
  649. Deliberate Syntax Error
  650. #endif                    /* AMIGA || ATARI_ST || ... */
  651.  
  652. #if MSDOS
  653. #if MICROSOFT
  654.    /*
  655.     * Get the locations from the INCLUDE environment variable.
  656.     */
  657.    s = syspath;
  658.    if (*s != '\0')
  659.       incl_search[j++] = s;
  660.    while (*s != '\0') {
  661.       if (*s == ';') {
  662.          *s = '\0';
  663.          ++s;
  664.          if (*s != '\0')
  665.             incl_search[j++] = s;
  666.          }
  667.       else {
  668.          if (*s == '\\')
  669.             *s = '/';
  670.          ++s;
  671.          }
  672.       }
  673. #endif                    /* MICROSOFT */
  674.  
  675. #if TURBO || BORLAND_286 || BORLAND_386
  676.     /*
  677.      * Get the locations from the -I options in the configuration file.
  678.      */
  679.     if (cfg_file != NULL) {
  680.        rewind(cfg_file);
  681.        sbuf = get_sbuf();
  682.        c = getc(cfg_file);
  683.        while (c != EOF) {
  684.           if (c == '-') {
  685.              if ((c = getc(cfg_file)) == 'I') {
  686.                 c = getc(cfg_file);
  687.                 while (c != ' ' && c != '\t' && c != '\n' && c != EOF) {
  688.                    AppChar(*sbuf, c);
  689.                    c = getc(cfg_file);
  690.                    }
  691.                 incl_search[j++] = str_install(sbuf);
  692.                 }
  693.              }
  694.           else
  695.              c = getc(cfg_file);
  696.           }
  697.        rel_sbuf(sbuf);
  698.        fclose(cfg_file);
  699.        }
  700. #endif                     /* TURBO || BORLAND_286 ... */
  701.  
  702. #if HIGHC_386 || INTEL_386 || WATCOM
  703.   /* something is needed */
  704. #endif                    /* HIGHC_386 || INTEL_386 || ... */
  705. #endif                    /* MSDOS */
  706.  
  707. #if UNIX || MACINTOSH
  708.    incl_search[n_paths - 1] = sysdir;
  709. #endif                    /* UNIX || MACINTOSH */
  710.  
  711. /*
  712.  * End of operating-system specific code.
  713.  */
  714.  
  715.    incl_search[n_paths] = NULL;
  716.    }
  717.  
  718. #if MACINTOSH
  719. #if MPW || THINK_C
  720. /*
  721.  * Extra functions specific to the Macintosh MPW implementation:
  722.  *  functions to convert a UNIX-type file name to Mac-type
  723.  *  and vice versa.
  724.  *
  725.  *  Result is pointer to a static string, or maybe a pointer
  726.  *  to the input string if it is unchanged.
  727.  */
  728.  
  729. static char FileName_newfn[100];
  730.  
  731. char *
  732. FileNameUnixToMac(char *fn) {
  733.   char *q,*e,*r;
  734.   int full;
  735.   
  736.   if (strchr(fn,'/') == NULL) return fn;
  737.   e = fn + strlen(fn);
  738.   r = FileName_newfn;
  739.   if (*fn == '/') {
  740.     full = 1;
  741.     ++fn;
  742.   }
  743.   else full = 0;
  744.   for (;;) {
  745.     (q = strchr(fn,'/')) || (q = e);
  746.     if (fn == q || q - fn == 1 && *fn == '.') {}
  747.     else if (q - fn == 2 && *fn == '.' && *(fn + 1) == '.')
  748.         *r++ = ':';
  749.     else {
  750.       *r++ = ':';
  751.       memcpy(r,fn,q - fn);
  752.       r += q - fn;
  753.     }
  754.     if (q == e) break;
  755.     fn = q + 1;
  756.   }
  757.   if (*(r - 1) == ':') *r++ = ':';
  758.   else if (*(e - 1) == '/') *r++ = ':';
  759.   *r = '\0';
  760.   return full ? FileName_newfn + 1 : FileName_newfn;
  761. }
  762.  
  763. char *
  764. FileNameMacToUnix(char *fn) {
  765.   char *q,*e,*r;
  766.   
  767.   if (strchr(fn,':') == NULL) return fn;
  768.   r = FileName_newfn;
  769.   if (*fn == ':') ++fn;
  770.   else *r++ = '/';
  771.   q = fn;
  772.   e = fn + strlen(fn);
  773.   for (;;) {
  774.     while (*fn == ':') {
  775.       ++fn;
  776.       memcpy(r,"../",3);
  777.       r += 3;
  778.     }
  779.     if (fn == e) break;
  780.     (q = strchr(fn,':')) || (q = e);
  781.     memcpy(r,fn,q - fn);
  782.     r += q - fn;
  783.     *r++ = '/';
  784.     if (q == e) break;
  785.     fn = q + 1;
  786.   }
  787.   *--r = '\0';
  788.   return FileName_newfn;
  789. }
  790.  
  791. /*
  792.  *  Helper function to make filename conversions more convenient.
  793.  *
  794.  *  This function calls either of the two above filename conversion functions
  795.  *  and returns the resulting filename in allocated memory.  Ownership of
  796.  *  the allocated memory is transferred to the caller -- i.e. it is the
  797.  *  caller's responsibility to eventually free it.
  798.  *
  799.  *  Example:  FileNameMacConvert(FileNameMacToUnix,":MyDir:MyFile")
  800.  */
  801. char *
  802. FileNameMacConvert(char *(*func)(char *),char *fn) {
  803.    char *newfp, *newmem;
  804.  
  805.    newfp = (*func)(fn);
  806.    newmem = (char *)malloc(strlen(newfp) + 1);
  807.    if (newmem == NULL) return NULL;
  808.    strcpy(newmem,newfp);
  809.    return newmem;
  810. }
  811. #endif                    /* MPW || THINK_C */
  812. #endif                    /* MACINTOSH */
  813.