home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Misc / DC-POS24.LZX / pOS / pOS_RKRM.lzx / pOS_RKRM / pDos / find.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-18  |  14.5 KB  |  474 lines

  1.  
  2. /*******************************************************************
  3.  $CRT 01 Jun 1996 : hb
  4.  
  5.  $AUT Holger Burkarth
  6.  $DAT >>find.c<<   08 Mar 1997    19:37:42 - (C) ProDAD
  7. *******************************************************************/
  8.  
  9. //##ex mcpp:cppc -gs -o pos:pos/Ex/find p:pLib/StartCode.o p:/pOS_RKRM/pDos/find.c p:pLib/StdIO.o -l pOSStub -l pOS
  10.  
  11. /***********************************************************
  12.   pOS programing example - Copyright (C) 1995-97 proDAD
  13.  
  14.   This code was written as an easy to understand example,
  15.   how to program pOS features. It is provided 'as-is',
  16.   without any express or implied warranty.
  17.  
  18.   Permission is hereby granted to use, copy and modify
  19.   this source code for any purpose, without fee, subject
  20.   to the following conditions:
  21.  
  22.     (1) This notice may not be removed or altered from any
  23.         source distribution.
  24.  
  25.     (2) Altered source versions must be plainly marked as
  26.         such, and must not be misrepresented as being
  27.         the original source code.
  28.  
  29.     (3) If only executable code is distributed, then the
  30.         accompanying documentation have to state that
  31.         "this software is based in part on examples of
  32.         the pOS developer packet".
  33.  
  34.     (4) Permission for use of this code is granted only
  35.         if the user accepts full responsibility for any
  36.         undesirable consequences. proDAD accept NO LIABILITY
  37.         for damages of any kind.
  38.  
  39.   ©proDAD
  40. ***********************************************************/
  41.  
  42. /*\
  43. *** Example:
  44. *** struct pOS_DosArgs
  45. *** struct pOS_AnchorPath
  46. *** struct pOS_PatternMatching
  47. *** struct pOS_FileHandle
  48. ***
  49. *** pOS_ReadDosArgs
  50. *** pOS_PathMatchFirst
  51. *** pOS_CURRANCHORPATH
  52. *** pOS_PathMatchNext
  53. *** pOS_PathMatchEnd
  54. *** pOS_DeleteDosArgs
  55. *** pOS_ConstructPattern
  56. *** pOS_ParsePatternA
  57. *** pOS_PrintDosErr
  58. *** pOS_DestructPattern
  59. *** pOS_AllocMem
  60. *** pOS_OpenFile
  61. *** pOS_FileGets
  62. *** pOS_MatchPattern
  63. *** pOS_CheckBreakSignal
  64. *** pOS_CloseFile
  65. *** pOS_FreeMem
  66. ***
  67. \*/
  68.  
  69. #define __COMPUTER_AMIGA 1
  70. #define NOMYDEBUG
  71.  
  72. #include "p:pExec/Types.h"
  73. #include "p:pDOS/ArgTags.h"
  74. #include "p:pDOS/ScanDir.h"
  75. #include "p:pDOS/Files.h"
  76. #include "p:pDOS/DosSig.h"
  77. #include "p:pDOS/DosErrors.h"
  78. #include "p:pDOS/FIB.h"
  79. #include "p:pDOS/Lock.h"
  80. #include "p:proto/pLibExt.h"
  81. #include "p:proto/pExec2.h"
  82. #include "p:proto/pDOS2.h"
  83.  
  84. #ifdef _____ME_____
  85.   #include "grund/inc_string.h"
  86.   #include "grund/inc_stdio.h"
  87. #else
  88.  #ifdef __cplusplus
  89.  extern "C" {
  90.  #endif
  91.   #include <string.h>
  92.   #include <stdio.h>
  93.  #ifdef __cplusplus
  94.  }
  95.  #endif
  96. #endif
  97.  
  98.  
  99. const CHAR *HelpText=
  100. "$H(PATTERN)"
  101. "Suchmuster, a#? sucht alle Files/Dirs, die mit 'a' beginnen"
  102. "$H(DIR)"
  103. "zu durchsuchende Verzeichnis(es)"
  104. "$H(FILES)"
  105. "Schaltet die Suche nach Files ein\n"
  106. "Falls kein FILES und DIRS angegeben wird,\n"
  107. "so werden nur Files gesucht."
  108. "$H(DIRS)"
  109. "Schaltet die Suche nach Directories ein"
  110. "$H(ALL)"
  111. "Erweitert die Suche auf Unterverzeichnisse"
  112. "$H(MA)"
  113. "Falls ein DIR ein MultiAssign ist, werden\n"
  114. "alle Möglichkeiten in die Suche einbezogen."
  115. "$H(DEPTH)"
  116. "Schränkt die Unterverzeichnis-Suche ein.\n"
  117. "Dieser Parameter wird nur in Verbindung mit ALL\n"
  118. "verwendet."
  119. "$H(SHOW)"
  120. "Zeigt den aktuellen Pfad an."
  121. "$H(PROMPT)"
  122. "Ausgabe-Schablone definieren. Z.B PROMPT=\"type %s*N\"\n"
  123. "Bei 'SEARCH' wird die gefundene Zeile in %ld ausgegeben."
  124. "$H(SEARCH)"
  125. "Sucht im File nach einem Muster.\n"
  126. "SEARCH=\"#?hallo#?\"\n"
  127. "  => sucht die Buchstabenabfolge 'hallo' bzw. 'HALLO'"
  128. "$H(BINARY)"
  129. "Sucht bei SEARCH nach Null-Bytes als Zeilenende. Sonst wird\n"
  130. "ein LF als Zeilenende interpretiert."
  131. ;
  132.  
  133. const CHAR *PrgHeader=
  134. "Files/Dirs finder\n"
  135. "find a#? b: all\n"
  136. " => sucht alle Dateien, die mit 'a' beginnen, in Laufwerk b\n"
  137. "Der Befehl kann jederzeit mit Ctrl-C unterbrochen werden."
  138. ;
  139.  
  140. const CHAR *PrgVerText=
  141. "$VER: 1.2 ("__DATE2__") (Copyright 1996-97 by proDAD) (Created by Holger Burkarth)";
  142.  
  143.  
  144. ULONG SearchFile(const pOS_FileLock*,const CHAR*,const pOS_PatternMatching*);
  145. ULONG SearchLFFile(const pOS_FileLock*,const CHAR*,const pOS_PatternMatching*);
  146. ULONG SearchBinFile(const pOS_FileLock*,const CHAR*,const pOS_PatternMatching*);
  147.  
  148.  
  149.  
  150. /*----------------------------------
  151. -----------------------------------*/
  152. #ifdef __cplusplus
  153. extern "C"
  154. #endif
  155.  
  156. VOID main()
  157. {
  158.   pOS_DosArgs* Args;
  159.   UWORD Err=0;
  160.   ULONG Ops[11]={0,0,0,0,0,0,16,0,0,0,0};
  161.  
  162.   Args=pOS_ReadDosArgs(
  163. // 0              1              2        3      4             5
  164. "PATTERN/A, DIR=DIRECTORY/A/M, FILES/S, DIRS/S, ALL/S, MA=MULTIASSIGN/S, "
  165. // 6          7        8         9          10
  166. "DEPTH/N/K, SHOW/S, PROMPT/K, SEARCH/K, BIN=BINARY/S",
  167. Ops,sizeof(Ops)/sizeof(ULONG),
  168.  
  169.     ARGTAG_PrgHeaderText, (ULONG)PrgHeader,    /* kurze Programm-Beschreibung */
  170.     ARGTAG_HelpText,      (ULONG)HelpText,     /* Help-Texte */
  171.     ARGTAG_PrgVerText,    (ULONG)PrgVerText,   /* VER-String */
  172.     ARGTAG_VarName,       (ULONG)"shell/find", /* Variable für die Default-Paramenter */
  173.     TAG_END);
  174.  
  175.   if(Args) {
  176.     struct {            /* zusammengesetzte Struct, damit ap_Buf sinnvoll eingesetzt werden kann */
  177.       pOS_AnchorPath AP;
  178.       CHAR Path[pOS_DosPathName_MAX];
  179.     } Scan;
  180.     pOS_PatternMatching PM;
  181.     SLONG Error=DOSERR_None;
  182.     ULONG PFlg=APF_PrtError; /* Scan-Errors werden autom. nach pr_CES ausgegeben */
  183.     ULONG FoundCnt=0;
  184.     __CONST__ CHAR **DirNames=(CHAR**)Ops[1];       /* DIR ist ein Multi-Paramenter */
  185.     static const CHAR *const PathFmt="\r%s\033[K";  /* Cursor an den Zeilenanfang und gesamte Zeile leeren */
  186.     static const CHAR *const CRLFmt="\r\033[K";     /* Clear-Line */
  187.  
  188.     pOS_ConstructPattern(&PM);
  189.  
  190.     if(Ops[5]) PFlg |= APF_MultiAssign;    /* MA erlauben */
  191.     if(Ops[9]) {                           /* SEARCH */
  192.       if(Ops[3]) {     /* DIRS */
  193.         Ops[3]=0;
  194.         printf("Argument 'SEARCH' excludes 'DIRS'.\n");
  195.       }
  196.       if(!pOS_ParsePattern(&PM,(CHAR*)Ops[9],0)) { /* Internes Pattern-Format erzeugen */
  197.         Error=(pOS_DosErrors)PM.pmt_Parse.ptmt_Error;
  198.         Err=DOSFAIL_FAIL;
  199.         pOS_PrintDosErr(NULL,(CHAR*)Ops[9],Error); /* Error ausgeben */
  200.       }
  201.     }
  202.     else if(Ops[10]) { // !SEARCH && BIN
  203.       printf("Argument BIN ist nur sinnvoll in Verbindung mit SEARCH.\n");
  204.     }
  205.  
  206.     if(Ops[2]==0 && Ops[3]==0) Ops[2]=1; /* default => FILES */
  207.  
  208. /*\
  209. *** ap_BufLen!=0, so wird der aktuelle Pfad autom. in ap_Buf aufgebaut.
  210. *** ap_BreakBits=DOSSIGF_CTRL_C => erlaubt ein ^C zum Abbruch,
  211. *** Error ist nach ^C auf DOSERR_ProgAborted gesetzt
  212. \*/
  213.     Scan.AP.ap_BreakBits=DOSSIGF_CTRL_C;
  214.     Scan.AP.ap_BufLen=pOS_DosPathName_MAX;
  215.  
  216.     if(Ops[7]) printf("\033[0 p"); // *** Cursor OFF (speed up)
  217.  
  218.     if(Error==DOSERR_None) {
  219.       for(; *DirNames ;++DirNames) {
  220.         UWORD Depth=*((ULONG*)Ops[6]);
  221.         UBYTE NeedLF=FALSE;
  222.  
  223. /*\
  224. *** Init. für den Scanner. Es ist ebenfalls möglich den Pfad+Pattern als
  225. *** Pfad zu übergeben.
  226. \*/
  227.         if(!(Error=pOS_PathMatchFirst(NULL,*DirNames,&Scan.AP,(CHAR*)Ops[0],PFlg))) {
  228.           if(!Ops[8]) printf("Search <%s> ...\n",*DirNames);
  229.  
  230. /*\
  231. *** Ersten bzw. nächsten Eintrag ermitteln. Die Pattern-Filterung wirkt sich
  232. *** nicht auf dieses Funktion aus, es werden immer alle Dateien ermittelt.
  233. *** Erst mittels (ap_Flags & APF_IsWild) wird geprüft, ob der Pattern-Vergleich
  234. *** positiv war. Am Directory-Ende wird als Error DOSERR_NoMoreEntries zurückgegeben.
  235. ***
  236. *** Der define pOS_CURRANCHORPATH() ermittelt das aktuelle Objekt. (read only)
  237. ***
  238. *** Nach jedem pOS_PathMatchNext() ist die Daten-Struct Obj->an_FIB gesetzt.
  239. \*/
  240.           while(!(Error=pOS_PathMatchNext(&Scan.AP)) ) {
  241.             const pOS_AnchorPathObj *const Obj=pOS_CURRANCHORPATH(&Scan.AP);
  242.  
  243.             if(Ops[7] && (Ops[9]==0 || (Scan.AP.ap_Flags & APF_IsWild)) ) {
  244.               printf(PathFmt,Scan.AP.ap_Buf);
  245.               NeedLF=TRUE;
  246.             }
  247.  
  248. /*\
  249. *** Ist das aktuelle Objekt ein DIR, so wird das 'APF_DoEnterDir' - Flag
  250. *** autom. gesetzt und als Kennung für den nächsten pOS_PathMatchNext()
  251. *** Durchlauf verwendet. Immer wenn das 'APF_DoEnterDir'-Flag gesetzt ist,
  252. *** wird in dieses DIR verzweigt. Ein gesetztes 'APF_ReturnDir'-Flag
  253. *** signalisiert, daß das DIR vollständig gelesen wurde und mit dem 'Parent'-Dir
  254. *** fortgefahren wird.
  255. \*/
  256.             if(Scan.AP.ap_Flags & APF_DoEnterDir) {
  257.               if(Ops[3] && (Scan.AP.ap_Flags & APF_IsWild)) { // DIRS
  258.                 if(NeedLF) {printf(CRLFmt); NeedLF=FALSE; }
  259.                 printf(Ops[8] ? (CHAR*)Ops[8]:"Found DIR  %s\n",Scan.AP.ap_Buf);
  260.                 ++FoundCnt;
  261.               }
  262.             }
  263.             else {
  264.               if(Ops[2] && (Scan.AP.ap_Flags & APF_IsWild)) { // FILES
  265.                 if(Ops[9]) {  // SEARCH
  266.                   ULONG Line;
  267. /*\
  268. *** Das Öffnen eines Files erfolgt über den Parent-Lock wesnetlich schneller,
  269. *** als über den gesamten Pfad. In jedem pOS_AnchorPathObj-Objekt ist immer der
  270. *** dazugehörige Lock vermerkt.
  271. \*/
  272.                   if(Ops[10]) Line=SearchBinFile(Obj->an_Lock,Obj->an_FIB.fib_FileName,&PM);
  273.                   else        Line=SearchLFFile(Obj->an_Lock,Obj->an_FIB.fib_FileName,&PM);
  274.                   if(Line) {
  275.                     if(NeedLF) {printf(CRLFmt); NeedLF=FALSE; }
  276.                     if(Line==~0) {         /* User-Abort Ctrl-C */
  277.                       Scan.AP.ap_FoundBreak |= DOSSIGF_CTRL_C; /* auto-abort in pOS_PathMatchNext */
  278.                     }
  279.                     else {
  280.                       printf(Ops[8] ? (CHAR*)Ops[8]:"Found FILE %s LINE %ld\n",Scan.AP.ap_Buf,Line);
  281.                       ++FoundCnt;
  282.                     }
  283.                   }
  284.                 }
  285.                 else {
  286.                   if(NeedLF) {printf(CRLFmt); NeedLF=FALSE; }
  287.                   printf(Ops[8] ? (CHAR*)Ops[8]:"Found FILE %s\n",Scan.AP.ap_Buf);
  288.                   ++FoundCnt;
  289.                 }
  290.               }
  291.             }
  292.             if(!Ops[4]) Scan.AP.ap_Flags &= ~APF_DoEnterDir; // *** ALL
  293.  
  294.             if(Scan.AP.ap_Flags & APF_DoEnterDir) {
  295.               if(Depth==0) {
  296.                 Scan.AP.ap_Flags &= ~APF_DoEnterDir;
  297.                 if(NeedLF) {printf(CRLFmt); NeedLF=FALSE; }
  298.                 if(!Ops[8]) printf("Max Depth, abort deep-scan\n");
  299.               }
  300.               else --Depth;
  301.             }
  302.             if(Scan.AP.ap_Flags & APF_ReturnDir)  ++Depth;
  303.           }
  304.         }
  305.  
  306. /*\
  307. *** Nach einem pOS_PathMatchFirst() muß immer pOS_PathMatchEnd() aufgerufen werden.
  308. *** (auch im Fehlerfall)
  309. \*/
  310.         pOS_PathMatchEnd(&Scan.AP);
  311.  
  312.         if(NeedLF) {printf(CRLFmt); NeedLF=FALSE; }
  313.  
  314.         if(Error && Error!=DOSERR_NoMoreEntries) {
  315.           Err=DOSFAIL_ERROR; /* größerer Fehler aufgetreten */
  316.           break;
  317.         }
  318.       }
  319.     }
  320.     if(Ops[7]) printf("\033[1 p"); // *** Cursor ON
  321.  
  322.     if(Err==0 && FoundCnt==0) Err=DOSFAIL_WARN; /* es wurde kein passendes File/Dir gefunden */
  323.  
  324.     pOS_DestructPattern(&PM); /* Pattern-Datas freigeben */
  325.     pOS_DeleteDosArgs(Args);  /* Args freigeben */
  326.   }
  327.   else Err=DOSFAIL_FAIL;  /* vollkommen fehlgeschlagen */
  328.  
  329. //  pOS_ExitProcess(Err);
  330. }
  331.  
  332.  
  333. #if 0
  334. /*----------------------------------
  335. Sucht im File nach einem Muster und ermittelt die Zeilennummer.
  336. -----------------------------------*/
  337. ULONG SearchFile(const pOS_FileLock* lk,const CHAR* name,
  338.                  const pOS_PatternMatching* pm)
  339. {
  340.   pOS_FileHandle* FH;
  341.   const size_t BufSize=2048;
  342.   UBYTE *Buffer;
  343.   BOOL Flg=FALSE;
  344.   ULONG Line=0;
  345.  
  346. /*\
  347. *** Das File wird relativ zum Lock geöffnet (geht schneller).
  348. *** Die Fuktion pOS_MatchPattern durchsucht jede Textzeile nach dem Muster.
  349. \*/
  350.   if(Buffer=(UBYTE*)pOS_AllocMem(BufSize,MEMF_PUBLIC)) {
  351.     if(FH=pOS_OpenFile(lk,name,FILEHDMOD_Read)) {
  352.       while(pOS_FileGets(FH,Buffer,BufSize-1)) {
  353.         ++Line;
  354.         if(pOS_MatchPattern(pm->pmt_First,Buffer)) {
  355.           Flg=TRUE;
  356.           break;
  357.         }
  358. /*\
  359. *** Der User hat Ctrl-C gedrückt, das C-Flag wird autom. zurückgesetzt, so daß
  360. *** ein zweiter Aufruf keinen Break anzeigt.
  361. \*/
  362.         if(pOS_CheckBreakSignal()) {
  363.           Flg=TRUE; Line=~0;
  364.           break;
  365.         }
  366.       }
  367.       pOS_CloseFile(FH);
  368.     }
  369.     else printf("Cannot open file <...%s>\n",name);
  370.     pOS_FreeMem(Buffer,BufSize);
  371.   }
  372.   else printf("Cannot allocate buffer.\n");
  373.   return(Flg ? Line:0);
  374. }
  375. #endif
  376.  
  377.  
  378. /*----------------------------------
  379. -----------------------------------*/
  380. ULONG SearchBinFile(const pOS_FileLock* lk,const CHAR* name,
  381.                  const pOS_PatternMatching* pm)
  382. {
  383.   pOS_FileHandle* FH;
  384.   size_t Pos,BufSize;
  385.   UBYTE *Buffer,*Buf;
  386.   BOOL Flg=FALSE;
  387.   ULONG Line=0;
  388.  
  389.   if(FH=pOS_OpenFile(lk,name,FILEHDMOD_Read)) {
  390.     BufSize=FH->fh_Size;
  391.     if(BufSize>1) {
  392.       if(Buffer=(UBYTE*)pOS_AllocMem(BufSize+1,MEMF_PUBLIC)) {
  393.         if(BufSize==pOS_ReadFile(FH,Buffer,BufSize)) {
  394.           Buffer[BufSize]='\0'; // *** End-Marke
  395.           for(Buf=Buffer; Line<BufSize; Line+=Pos,Buf+=Pos) {
  396.             Pos=strlen(Buf)+1;
  397.             if(pOS_MatchPattern(pm->pmt_First,Buf)) {
  398.               Flg=TRUE;
  399.               break;
  400.             }
  401.  
  402.             if(pOS_CheckBreakSignal()) {
  403.               Flg=TRUE; Line=~0;
  404.               break;
  405.             }
  406.           }
  407.         }
  408.         else printf("Read-Error in <%s>\n",name);
  409.  
  410.         pOS_FreeMem(Buffer,BufSize+1);
  411.       }
  412.       else printf("Cannot allocate buffer. [%ld Bytes]\n",BufSize);
  413.     }
  414.     else printf("File <%s> is too small.\n",name);
  415.     pOS_CloseFile(FH);
  416.   }
  417.   else printf("Cannot open file <...%s>\n",name);
  418.   return(Flg ? Line:0);
  419. }
  420.  
  421. /*----------------------------------
  422. -----------------------------------*/
  423. ULONG SearchLFFile(const pOS_FileLock* lk,const CHAR* name,
  424.                  const pOS_PatternMatching* pm)
  425. {
  426.   pOS_FileHandle* FH;
  427.   size_t Pos,BufSize;
  428.   UBYTE *Buffer,*Buf,*Buf2;
  429.   BOOL Flg=FALSE;
  430.   ULONG Line;
  431.  
  432.   if(FH=pOS_OpenFile(lk,name,FILEHDMOD_Read)) {
  433.     BufSize=FH->fh_Size;
  434.     if(BufSize>1) {
  435.       if(Buffer=(UBYTE*)pOS_AllocMem(BufSize+1,MEMF_PUBLIC)) {
  436.         if(BufSize==pOS_ReadFile(FH,Buffer,BufSize)) {
  437.           Buffer[BufSize]='\0'; // *** End-Marke
  438.  
  439. /*\
  440. *** Alle LF und CR in \0 umwandeln.
  441. \*/
  442.           for(Buf=Buffer; (ULONG)Buf<(ULONG)&Buffer[BufSize]; Buf=Buf2+1) {
  443.             Buf2=strpbrk(Buf,"\n\r");
  444.             if(Buf2) Buf2[0]='\0';
  445.             else break;
  446.           }
  447.  
  448.           for(Buf=Buffer,Line=0; Line<BufSize; Line+=Pos,Buf+=Pos) {
  449.             Pos=strlen(Buf)+1;
  450.             if(pOS_MatchPattern(pm->pmt_First,Buf)) {
  451.               Flg=TRUE;
  452.               break;
  453.             }
  454.  
  455.             if(pOS_CheckBreakSignal()) {
  456.               Flg=TRUE; Line=~0;
  457.               break;
  458.             }
  459.           }
  460.         }
  461.         else printf("Read-Error in <%s>\n",name);
  462.  
  463.         pOS_FreeMem(Buffer,BufSize+1);
  464.       }
  465.       else printf("Cannot allocate buffer. [%ld Bytes]\n",BufSize);
  466.     }
  467.     else printf("File <%s> is too small.\n",name);
  468.     pOS_CloseFile(FH);
  469.   }
  470.   else printf("Cannot open file <...%s>\n",name);
  471.   return(Flg ? Line:0);
  472. }
  473.  
  474.