home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume10 / ifp / part05 / interp / file.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-07-06  |  13.0 KB  |  526 lines

  1.  
  2. /****** file.c ********************************************************/
  3. /**                                                                  **/
  4. /**                    University of Illinois                        **/
  5. /**                                                                  **/
  6. /**                Department of Computer Science                    **/
  7. /**                                                                  **/
  8. /**   Tool: IFP                         Version: 0.5                 **/
  9. /**                                                                  **/
  10. /**   Author:  Arch D. Robison          Date:   May 1, 1985          **/
  11. /**                                                                  **/
  12. /**   Revised by: Arch D. Robison       Date: June 22, 1986          **/
  13. /**                                                                  **/
  14. /**   Principal Investigators: Prof. R. H. Campbell                  **/
  15. /**                            Prof. W. J. Kubitz                    **/
  16. /**                                                                  **/
  17. /**                                                                  **/
  18. /**------------------------------------------------------------------**/
  19. /**   (C) Copyright 1987  University of Illinois Board of Trustees   **/
  20. /**                       All Rights Reserved.                       **/
  21. /**********************************************************************/
  22.  
  23.  
  24. #include <stdio.h>
  25. #include "struct.h"
  26. #include "string.h"
  27. #include "node.h"
  28. #include "umax.h"
  29. #include "inob.h"
  30.  
  31. extern char *strcpy (),*strcat (),*getenv ();
  32.  
  33. /*------------------------- Operating System Constants --------------------*
  34.  *
  35.  * Operating System Constants
  36.  *
  37.  * PATH_SEPARATOR = separator used for file names
  38.  * EDITOR = path to editor
  39.  * EdCommand = IFP command to invoke EDITOR
  40.  *
  41.  * Even operating systems without hierarchical file systems must
  42.  * define a PATH_SEPARATOR, which is used still used internally.
  43.  *
  44.  * In the case of CTSS, we also have a constant USER_PATH.  This
  45.  * a fictious path to the user's current directory. 
  46.  */ 
  47.  
  48. #if OPSYS==UNIX
  49. #define PATH_SEPARATOR '/'
  50. #define EDITOR "/bin/vi"
  51. char *EdCommand;
  52. #endif
  53.  
  54. #if OPSYS==MSDOS
  55. #define PATH_SEPARATOR '\\'
  56. #define EDITOR "c:ed.exe"
  57. char *EdCommand = "ed";
  58. char DirPath [MAXPATH+1] = "c:dir.exe";
  59. #endif
  60.  
  61. #if OPSYS==CTSS
  62. #define PATH_SEPARATOR '/'
  63. #define EDITOR "fred"
  64. char *EdCommand = "fred";
  65. #define USER_PATH "/usr"
  66. #endif
  67.  
  68. /*-------------------- end of Operating System Constants --------------------*/
  69.  
  70. char RootPath [MAXPATH+1] = "";         /* Path to IFP's root */
  71.  
  72. char EditorPath [MAXPATH+1] = EDITOR;   /* value is default */
  73.  
  74. char FPprompt[16] = "ifp> ";   /* value is default */
  75. NodePtr CurWorkDir = NULL;     /* Current working directory node */
  76.  
  77. /********************** Operating system file interface ***********************/
  78.  
  79. /*
  80.  * PathTail
  81.  *
  82.  * Return the last component in a path name.
  83.  * Returns pointer to "" if error occurs.
  84.  */
  85. private char *PathTail (Path)
  86.    char *Path;
  87.    {
  88.       register char *T;
  89.  
  90.       if (*Path == PATH_SEPARATOR) Path++;
  91.       while (*Path) {
  92.      for (T = Path; *T++ != PATH_SEPARATOR; )
  93.         if (!*T) return Path;
  94.      Path = T;
  95.       }
  96.       return Path;
  97.    }
  98.  
  99. /*------------------------------ fopen hacks ------------------------------
  100.  *
  101.  * Both MSDOS and CTSS have problems with hierarchical file structure.
  102.  * Thus we have to redefine the standard UNIX function "fopen" to allow
  103.  * for these operating system's quirks.
  104.  */
  105. #if OPSYS==MSDOS
  106.  
  107. /*
  108.  * We try to keep track of the current directory in CWDCache so we can avoid
  109.  * superfluous calls to chdir.  Set the 0th character to '\0' to empty the
  110.  * cache.
  111.  */
  112. char CWDCache [MAXPATH] = "";
  113.  
  114. /*
  115.  * PathSplit
  116.  *
  117.  * Split a pathname into its directory and file parts.
  118.  * Change directory to directory part.
  119.  *
  120.  * Input
  121.  *      PathName = pathname
  122.  *
  123.  * Output
  124.  *      NULL if error occurs, pointer to file name otherwise.
  125.  */
  126. char *PathSplit (PathName)      /* also used by command.c */
  127.    char *PathName;
  128.    {
  129.       register char *S,*T;
  130.       register int R;
  131.  
  132.       T = PathTail (PathName);
  133.       if (T != &PathName [1]) {
  134.      T[-1] = '\0';
  135.      S = PathName;          /* Break string at path separator */
  136.       } else S = "\\";
  137.       if (strcmp (S,CWDCache)) {
  138.      R = chdir (S);
  139.      if (Debug & DebugFile) printf ("cache load: %d = ChDir (%s) for %s\n",R,S,T);
  140.      (void) strcpy (CWDCache,S);
  141.       } else {
  142.      if (Debug & DebugFile) printf ("cache HIT!\n"); 
  143.      R = 0;
  144.       }
  145.       T[-1] = PATH_SEPARATOR;   /* Replace path separator */
  146.       return R ? NULL : T;
  147.    }
  148.  
  149. /*
  150.  * DOSfopen
  151.  *
  152.  * Works as =`fopen' should.  The old Lattice C `fopen' would not take 
  153.  * pathnames.  Even though the new compiler's will allow long names,
  154.  * the fake fopen can take advantage of the current directory cache.
  155.  */
  156. private FILE *DOSfopen (FileName,Mode)
  157.    char *FileName,*Mode;
  158.    {
  159.       char *T;
  160.  
  161.       return (T = PathSplit (FileName)) != NULL ? fopen (T,Mode) : NULL;
  162.    }
  163.  
  164. #define fopen DOSfopen
  165.  
  166. #endif /* OPSYS==MSDOS */
  167.  
  168. #if OPSYS==CTSS
  169. /*
  170.  * CTSSfopen
  171.  *
  172.  * Tries for fake a real fopen.  CTSS does not support hierarchical file
  173.  * structures, so CTSSfopen takes the tail of the path as the file name.
  174.  */
  175. private FILE *CTSSfopen (FileName,Mode)
  176.    char *FileName,*Mode;
  177.    {
  178.       register char *T;
  179.  
  180.       if (Debug & DebugFile) printf ("CTSSfopen (%s,%s)\n",FileName,Mode);
  181.       T = PathTail (FileName);
  182.       if (T == &FileName[1]) return NULL;
  183.       else {
  184.      T[-1] = '\0';
  185.      if (strcmp (FileName,USER_PATH)) return NULL;
  186.      else {
  187.         if (Debug & DebugFile) printf ("fopen (%s,%s)\n",T,Mode);
  188.         return fopen (T,Mode);
  189.      }
  190.       }
  191.    }
  192. #define fopen CTSSfopen
  193.  
  194. #endif /* OPSYS==CTSS */
  195.  
  196. /*---------------------------- end of fopen hacks ----------------------------*/
  197.  
  198. /*
  199.  * FormNPath
  200.  *
  201.  * Create the pathname for a given node.
  202.  *
  203.  * Input
  204.  *      N = pointer to node
  205.  *      PathLim = pointer to end of PathName buffer
  206.  *
  207.  * Output
  208.  *      Pathname for node
  209.  */
  210. char *FormNPath (N,PathName,PathLim)
  211.    register NodePtr N;
  212.    char PathName[];
  213.    register char *PathLim;
  214.    {
  215.       CharPtr U;
  216.       register char *T;
  217.  
  218.       if (N->NodeParent == NULL) {
  219.      (void) strcpy (PathName,RootPath);
  220.      return &PathName [strlen (PathName)];
  221.       } else {
  222.      T = FormNPath (N->NodeParent,PathName,PathLim);
  223.      if (T==NULL) return NULL;
  224.      else {
  225.         *T++ = PATH_SEPARATOR;
  226.         CPInit (&U,&N->NodeName);
  227.         (void) CPRead (&U,T,PathLim-T);
  228. #if OPSYS==UNIX
  229.         T += strlen (T);
  230. #endif
  231. #if OPSYS==MSDOS || OPSYS==CTSS 
  232.         /* DOS and CTSS names limited to 8 characters */
  233.         {
  234.            int L;               
  235.            if ((L = strlen (T)) > 8) L = 8;
  236.            *(T += L) = '\0';
  237.         }
  238. #endif
  239.         if (!CPRead (&U,T,PathLim-T)) return T;
  240.         else return NULL; /* U should be empty */
  241.      }
  242.       }
  243.    }
  244.  
  245.  
  246. /*
  247.  * FormPath
  248.  *
  249.  * Make UNIX or DOS pathname for node
  250.  *
  251.  * Input
  252.  *      N = node or path list
  253.  *      PathName = buffer to put pathname in.
  254.  *      PathLim = pointer to end of buffer
  255.  *
  256.  * Output
  257.  *      PathName = pathname if successful
  258.  */
  259. void FormPath (N,PathName,PathLim)
  260.    register ObjectPtr N;
  261.    char PathName[];
  262.    char *PathLim;
  263.    {
  264.       register char *T;
  265.       CharPtr U;
  266.       register ListPtr P;
  267.       register int K;
  268.  
  269.       switch (N->Tag) {
  270.  
  271.      case LIST:
  272.         (void) strcpy (PathName,RootPath);
  273.         K = strlen (PathName);
  274.         PathLim -= K;
  275.         T = &PathName [K];
  276.         for (P = N->List; P!=NULL; P=P->Next) {
  277.            if (P->Val.Tag != STRING) return;
  278.            else {
  279.           CPInit (&U,&P->Val.String);
  280.           (void) CPRead (&U,T,PathLim-PathName);
  281. #if OPSYS==UNIX
  282.           T += strlen (T);
  283. #endif
  284. #if OPSYS==MSDOS || OPSYS==CTSS 
  285.           /* DOS names are limited to 8 characters */
  286.           if ((K = strlen (T)) > 8) K = 8; 
  287.           *(T += K) = '\0';
  288. #endif
  289.           /* T should always be <= PathLim */
  290.           if (T >= PathLim) return;
  291.            }
  292.         }
  293.         break;
  294.  
  295.      case NODE:
  296.         (void) FormNPath (N->Node,PathName,PathLim);
  297.         break;
  298.  
  299.      default:
  300.         break;
  301.       }
  302.    }
  303.  
  304. /*
  305.  * ReadDef
  306.  *
  307.  * Read a definition node.  The definition node tag must be BOTTOM upon entry
  308.  * when running UMAX.
  309.  *
  310.  * Input
  311.  *      Caller = pointer to DEF node of caller
  312.  *      Fun = object with tag NODE.  
  313.  */
  314. void ReadDef (Caller,Fun)
  315.    NodePtr Caller;
  316.    ObjectPtr Fun;
  317.    {
  318.       NodePtr N;
  319.       char FileName[MAXPATH];
  320.       FILE *DefFile;
  321.       InDesc F;
  322.       int C;
  323.  
  324.  
  325.       if (NULL == FormNPath (N=Fun->Node,FileName,&FileName[MAXPATH])) 
  326.      DefError (Caller,Fun,"invalid name for function");
  327.       else 
  328.      while (NULL != (DefFile = fopen (FileName,"r"))) {
  329.         InitIn (&F,N->NodeParent,DefFile,0);
  330.         C = InDef (&F,N->NodeName,&N->NodeData.NodeDef.DefCode);
  331.         (void) fclose (F.InFile);
  332.         if (C) goto exit;
  333.         printf ("Do you wish to edit %s ? ",FileName + strlen (RootPath));
  334.         while (1) {
  335.            for (C = getchar (); getchar ()!='\n';) continue;
  336.            if (C == 'y') {
  337.           ExecEdit (FileName); 
  338.           break;
  339.            }
  340.            if (C == 'n') goto exit;
  341.            printf ("Respond with y or n\n");
  342.         }
  343.      } 
  344. exit:;
  345.    }
  346.  
  347. /*
  348.  * ReadImport
  349.  *
  350.  * Read the import file for a module node.
  351.  *
  352.  * Input
  353.  *      M = pointer to module node
  354.  */
  355. void ReadImport (M)
  356.    NodePtr M;
  357.    {
  358.       char *T;
  359.       char FileName[MAXPATH];
  360.       FILE *ImpFile;
  361.       InDesc F;
  362.  
  363.       if (NULL != (T = FormNPath (M,FileName,&FileName[MAXPATH]))) {
  364.      *T++ = PATH_SEPARATOR;
  365.      (void) strcpy (T,"%IMPORT");
  366.      if (NULL != (ImpFile = fopen (FileName,"r"))) {
  367.         InitIn (&F,M,ImpFile,0);
  368.         InImport (&F,M);
  369.         (void) fclose (ImpFile);
  370.      }
  371.       }
  372.    }
  373.  
  374. #if OPSYS!=CTSS
  375. /*
  376.  * EnvGet
  377.  *
  378.  * Get value for environment variable.
  379.  *
  380.  * Input
  381.  *      Key = enviroment variable name
  382.  *      Value = default value for variable
  383.  *      ValLim = length of Value buffer
  384.  *
  385.  * Output
  386.  *      Value = value of enviroment variable, or default if not found.
  387.  */
  388. void EnvGet (Key,Value,ValLim)
  389.    char *Key,*Value;
  390.    int ValLim;
  391.    {
  392.       char *V;
  393.  
  394.       V = getenv (Key);
  395.       if (V != NULL)
  396.      if (strlen (V) < ValLim) (void) strcpy (Value,V);
  397.      else fprintf (stderr,"Error: %s in enviroment is longer than %d\n",
  398.                Key,MAXPATH-3);
  399.    }
  400.  
  401.  
  402. /*
  403.  * CWDGet
  404.  *
  405.  * Find pathname of current working directory (relative to FP root).
  406.  *
  407.  * Input
  408.  *      PathLim = length of Path buffer (used by PCAT versions only)
  409.  *
  410.  * Output
  411.  *      result = 1 if valid FP path, 0 otherwise
  412.  *      Path = FP pathname if valid, undefined otherwise
  413.  */
  414. boolean CWDGet (Path,PathLim)
  415.    register char *Path;
  416.    int PathLim;
  417.    {
  418. #ifdef PCAT
  419.       extern char *getcwd ();
  420.       if (!getcwd (Path,PathLim-2)) return 0;
  421. #else
  422. #if S9000
  423.       extern FILE *popen ();
  424.       FILE *F;                          /* S9000 Xenix has no getwd! */
  425.       F = popen ("/bin/pwd","r");
  426.       fscanf (F,"%s",Path);
  427.       pclose (F);
  428. #else
  429.       extern char *getwd();
  430.       if (!getwd (Path)) return 0;
  431. #endif /* S9000 */
  432. #endif /* PCAT */
  433.  
  434. #if OPSYS==MSDOS
  435.       (void) strcpy (Path,Path+2);              /* Delete drive name */
  436.       if (Debug & DebugFile) printf ("CWD = '%s'\n",Path); 
  437.       return 1;
  438. #endif
  439. #if OPSYS==UNIX
  440.       {
  441.      register int K;
  442.      K = strlen (RootPath);
  443.      if (strncmp (Path,RootPath,K)) return 0;
  444.      else {
  445.         (void) strcpy (Path,&Path[K]);    /* Remove FP root path prefix */
  446.         return 1;
  447.      }
  448.       }
  449. #endif
  450.    }
  451. #endif /* OPSYS != CTSS */
  452.  
  453. /*
  454.  * InitFile
  455.  *
  456.  * The DOS version is kludgy.  The problem is that DOSfopen changes 
  457.  * the current directory, thus munging it before CWDGet is called.
  458.  */
  459. #if OPSYS==UNIX || OPSYS==CTSS
  460. void InitFile ()
  461. #endif
  462. #if OPSYS==MSDOS
  463. void InitFile (CWD)
  464.    char *CWD;
  465. #endif
  466.    {
  467.       Object X;
  468.       InDesc F;
  469.  
  470.       if (Debug & DebugFile) printf ("enter InitFile\n");
  471. #if OPSYS!=CTSS
  472.       EnvGet ("EDITOR",EditorPath,MAXPATH);
  473. #endif
  474.       if (Debug & DebugFile) printf ("EditorPath = `%s'\n",EditorPath);
  475. #if OPSYS==UNIX
  476.       EdCommand = PathTail (EditorPath);
  477.       if (!*EdCommand) {
  478.      fprintf (stderr,"\n * EDITOR environment variable not a full path.");
  479.      fprintf (stderr,"\n   Setting editor to '%s'.\n",EDITOR);
  480.      EdCommand = PathTail (strcpy (EditorPath,EDITOR));
  481.       }
  482.       EnvGet ("IFPprompt",FPprompt,sizeof (FPprompt));
  483. #endif
  484. #if OPSYS==MSDOS
  485.       EnvGet ("IFPDIR",DirPath,MAXPATH);
  486.       if (Debug & DebugFile) printf ("IFPDIR = '%s'\n",DirPath);
  487. #endif
  488.  
  489.       /* Create dummy descriptor for scanning environment info */
  490.       InitIn (&F,(NodePtr) NULL,(FILE *) NULL, -1); 
  491.  
  492. #if OPSYS==UNIX
  493.       if (!CWDGet (F.InBuf,INBUFSIZE-1)) {
  494.      fprintf (stderr,"\n\n * Current directory not a IFP subdirectory.");
  495.      fprintf (stderr,  "\n   Setting current directory to IFP root.\n");
  496.      if (chdir (RootPath)) {
  497.         extern int errno;
  498.         perror (RootPath);
  499.         exit (errno);
  500.      } else F.InBuf[0] = '\0';
  501.       }
  502. #endif
  503. #if OPSYS==MSDOS
  504.       {
  505.      register char *T;
  506.      (void) strcpy (F.InBuf,CWD);
  507.      for (T=F.InBuf; *T; T++)
  508.         if (*T == PATH_SEPARATOR) *T = '/';
  509.       }
  510. #endif
  511. #if OPSYS==CTSS
  512.       (void) strcpy (F.InBuf,USER_PATH);
  513. #endif
  514.       if (F.InBuf[0]) {
  515.      (void) strcat (F.InPtr,"\n");
  516.      (void) InNode (&F,&X,NIL);
  517.      CurWorkDir = MakeNode (X.List,1);
  518.       } else 
  519.      CurWorkDir = RootNode;
  520.       if (Debug & DebugFile) printf ("exit InitFile\n");
  521.    }
  522.  
  523.  
  524. /************************* end of file.c *******************************/
  525.  
  526.