(* DynamicPath.mod implements a path for DynamicStrings. Copyright (C) 2001-2023 Free Software Foundation, Inc. Contributed by Gaius Mulley . This file is part of GNU Modula-2. GNU Modula-2 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNU Modula-2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Under Section 7 of GPL version 3, you are granted additional permissions described in the GCC Runtime Library Exception, version 3.1, as published by the Free Software Foundation. You should have received a copy of the GNU General Public License and a copy of the GCC Runtime Library Exception along with this program; see the files COPYING3 and COPYING.RUNTIME respectively. If not, see . *) IMPLEMENTATION MODULE DynamicPath ; (*!m2iso+gm2*) FROM Storage IMPORT ALLOCATE, DEALLOCATE ; FROM DynamicStrings IMPORT InitString, ConCat, ConCatChar, char, Dup, KillString, Length, EqualArray ; FROM SFIO IMPORT Exists ; FROM FIO IMPORT StdErr ; FROM M2Printf IMPORT fprintf0, fprintf1 ; CONST Directory = '/' ; Debugging = FALSE ; TYPE PathList = POINTER TO RECORD tail, next : PathList ; entry: String ; END ; VAR FreeList: PathList ; (* KillPathList - places list pl onto the freelist. Postcondition: pl will be NIL. *) PROCEDURE KillPathList (VAR pl: PathList) ; BEGIN IF pl # NIL THEN pl^.tail^.next := FreeList ; FreeList := pl ; pl := NIL END END KillPathList ; (* InitPathList - creates a new empty path list. It takes a copy of the string. *) PROCEDURE InitPathList (str: String) : PathList ; VAR pl: PathList ; BEGIN NEW (pl) ; WITH pl^ DO tail := pl ; next := NIL ; entry := Dup (str) END ; RETURN pl END InitPathList ; (* Cons - appends str to the end of a path list. If pl is NIL a new list is created and returned containing str. *) PROCEDURE Cons (pl: PathList; str: String) : PathList ; BEGIN IF pl = NIL THEN pl := InitPathList (str) ELSE pl := ConsList (pl, InitPathList (str)) END ; RETURN pl END Cons ; (* ConsList - concatenates path list left and right together. *) PROCEDURE ConsList (left, right: PathList) : PathList ; BEGIN IF right # NIL THEN left^.tail^.next := right ; left^.tail := right^.tail END ; RETURN left END ConsList ; (* Stash - returns pl before setting pl to NIL. *) PROCEDURE Stash (VAR pl: PathList) : PathList ; VAR old: PathList ; BEGIN old := pl ; pl := NIL ; RETURN old END Stash ; (* AddDir - if str is not empty and does not end with / then add a directory. Postcondition: str is returned (with a '/' at the end) or is empty. *) PROCEDURE AddDir (str: String) : String ; BEGIN IF Length (str) > 0 THEN IF char (str, -1) # Directory THEN str := ConCatChar (str, Directory) END END ; RETURN str END AddDir ; (* FindFileName - returns NIL if a file cannot be found otherwise it returns the path including the filename. *) PROCEDURE FindFileName (filename: String; pl: PathList) : String ; VAR s: String ; BEGIN WHILE pl # NIL DO s := ConCat (AddDir (Dup (pl^.entry)), Dup (filename)) ; IF Debugging THEN fprintf1 (StdErr, "testing for %s: ", s) END ; IF Exists (s) THEN IF Debugging THEN fprintf0 (StdErr, "yes\n") END ; RETURN s END ; IF Debugging THEN fprintf0 (StdErr, "no\n") END ; s := KillString (s) ; pl := pl^.next END ; IF Debugging THEN fprintf1 (StdErr, "FindFileName did not find: %s in path\n", filename) END ; RETURN NIL END FindFileName ; (* DumpPath - debugging dump of the pathlist. *) PROCEDURE DumpPath (name: String; pl: PathList) ; BEGIN fprintf1 (StdErr, "%s:", name) ; WHILE pl # NIL DO fprintf0 (StdErr, " {") ; fprintf1 (StdErr, "%s", pl^.entry) ; fprintf0 (StdErr, "}") ; pl := pl^.next END ; fprintf0 (StdErr, "\n") END DumpPath ; BEGIN FreeList := NIL END DynamicPath.