home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 2 / goldfish_vol2_cd2.bin / bbs / dev / amiga_e-3.0a.lha / Amiga_E / Src / Utils / D.e < prev    next >
Text File  |  1992-09-02  |  10KB  |  295 lines

  1. /* recursive directory tool
  2.  
  3. needs v37.
  4.  
  5. Universal directory lister. called with no arguments, by just typing
  6. "d", it lists the current directory. template:
  7.  
  8. DIR,REC/S,COL/K/N,SIZE/S,NOSORT/S,NOFILES/S,NODIRS/S,FULL/S,NOANSI/S,
  9. TARGET/K,DO/K/F
  10.  
  11. DIR        specifies an optional path to the dir you wish to list.
  12.         may contain standard wildcard patterns like #?~[]%() etc.
  13. REC        specifies that subdirectories should be listed recursively.
  14. COL <num>    where n=1..3, by default, D list dirs in three columns to
  15.         keep all nice and compact. specify 1 or 2 if you like.
  16. SIZE        reports the size of each dir as it is being listed. note that
  17.         combined with REC gives sizes of whole dir (sub-)trees.
  18. NOSORT        by default, dirs are sorted before display. disable this with
  19.         the NOSORT switch.
  20. NOFILES        displays just dirs
  21. NODIRS        displays just files
  22. FULL        lists full path instead of just filename
  23. NOANSI        doesn't use ansi display codes while printing
  24. TARGET <dir>    specifies a target directory for use with DO. should
  25.         end in either "/" or ":"
  26. DO <comline>    specifies a commandline for automatic script generation.
  27.         note that this uses up the rest of D's commandline.
  28.  
  29. something should be said on the script feature: it enables you
  30. to perform repetitive tasks on whole dirs, or dir-trees. existing
  31. utilities that enabled you to do such tasks where mostly not
  32. flexible enough; d enables you to use the REC keyword in combination
  33. with scripts, allows for variable extensions: use <file>.o if
  34. the original name was <file>.s, and the spec. of a target:
  35. resulting files from the operation are placed in another dir, which
  36. can be a complete mirror image of another dir-tree. makedir
  37. statements are inserted if target: is empty.
  38.  
  39. following format codes may be used in <commandline>:
  40.  
  41. %s is file (filename+path)
  42. %f is file WITHOUT extension
  43. %r is file without extension, but with leading <dir> replaced by
  44.    <target> (usefull if <commandline> allows for an outputfile)
  45. %> or %< %>> etc. prevents the shell from thinking ">" is a redirection
  46.    for D, instead of <commandline>
  47.  
  48. a complex example:
  49. you wish to have a complete ascii reference of the emodules:
  50. directory, recursively, and with the resulting .txt files
  51. as a mirror-image directory structure somewhere else.
  52.  
  53. 1> D >ram:script emodules: REC TARGET=t:mods/ DO showmodule %>%r.txt %s
  54. 1> execute ram:script
  55.  
  56. will do that for you.
  57. for any file like "emodules:exec/io.m" D will make a line like:
  58. "showmodule  >t:mods/exec/io.txt emodules:exec/io.m"
  59.  
  60. other examples:    D >mydirlist dh0: COL=2 SIZE REC NOANSI
  61.         D docs: DO type >prt: %s
  62.         D asm: TARGET=obj: DO genam %s -o%r.o
  63.         D emodules: REC TARGET=ram: DO showmodule %>%r.txt %s
  64.  
  65.  
  66. BUGS:
  67. none left.
  68.  
  69. IMPROVEMENTS OVER OLD "D"
  70. - remarkably faster
  71. - recursive
  72. - calculates filesizes of whole directory trees
  73. - one, two and three columns
  74. - wildcards
  75. - better/faster sort
  76. - better coding: handles dirs of any size
  77. - lots of options through standard readargs()
  78. - powerfull script generation
  79. - uses nested exception handlers to keep track of missed
  80.   MatchEnd() calls on a CtrlC and sudden errors.
  81.  
  82. */
  83.  
  84. OPT OSVERSION=37
  85.  
  86. CONST MAXPATH=250
  87.  
  88. ENUM ER_NONE,ER_BADARGS,ER_MEM,ER_UTIL,ER_ITARG,ER_COML
  89. ENUM ARG_DIR,ARG_REC,ARG_COL,ARG_SIZE,ARG_NOSORT,ARG_NOFILES,
  90.      ARG_NODIRS,ARG_FULL,ARG_NOANSI,ARG_TARGET,ARG_COMMAND,NUMARGS
  91.  
  92. MODULE 'dos/dosasl', 'dos/dos', 'utility'
  93.  
  94. RAISE ER_MEM IF New()=NIL,      /* set common exceptions:                */
  95.       ER_MEM IF String()=NIL,      /* every call to these functions will be */
  96.       ERROR_BREAK IF CtrlC()=TRUE /* automatically checked against NIL,    */
  97.                   /* and the exception ER_MEM is raised    */
  98.  
  99. DEF dir,command,target,
  100.     recf=FALSE,col=3,comf=FALSE,sizef=FALSE,sortf=TRUE,filesf=TRUE,
  101.     fullf=FALSE,ansif=TRUE,dirsf=TRUE,dirw[100]:STRING,
  102.     rdargs=NIL,work[250]:STRING,work2[250]:STRING,dirno=0,
  103.     prtab[25]:LIST,prcopy[25]:LIST,workdir[250]:STRING
  104.  
  105. PROC main() HANDLE
  106.   DEF args[NUMARGS]:LIST,templ,x,lock,fib:fileinfoblock,s
  107.   IF (utilitybase:=OpenLibrary('utility.library',37))=NIL THEN Raise(ER_UTIL)
  108.   FOR x:=0 TO NUMARGS-1 DO args[x]:=0
  109.   templ:='DIR,REC/S,COL/K/N,SIZE/S,NOSORT/S,NOFILES/S,NODIRS/S,' +
  110.          'FULL/S,NOANSI/S,TARGET/K,DO/K/F'
  111.   rdargs:=ReadArgs(templ,args,NIL)
  112.   IF rdargs=NIL THEN Raise(ER_BADARGS)        /* initialise flags */
  113.   IF args[ARG_SIZE] THEN sizef:=TRUE        /* from command line args */
  114.   IF args[ARG_COL] THEN col:=Long(args[ARG_COL])
  115.   IF args[ARG_NOSORT] THEN sortf:=FALSE
  116.   IF args[ARG_NOANSI] THEN ansif:=FALSE
  117.   IF args[ARG_NOFILES] THEN filesf:=FALSE
  118.   IF args[ARG_NODIRS] THEN dirsf:=FALSE
  119.   IF args[ARG_REC] THEN recf:=TRUE
  120.   IF args[ARG_FULL] THEN fullf:=TRUE
  121.   target:=args[ARG_TARGET]
  122.   command:=args[ARG_COMMAND]
  123.   IF command THEN comf:=TRUE
  124.   IF (col<>1) AND (col<>2) THEN col:=3
  125.   IF target
  126.     x:=target+StrLen(target)-1
  127.     IF (x<target) OR ((x[]<>":") AND (x[]<>"/")) THEN Raise(ER_ITARG)
  128.   ENDIF
  129.   IF comf
  130.     sortf:=FALSE    /* read and convert commandline for scripts */
  131.     col:=1
  132.     filesf:=FALSE
  133.     dirsf:=FALSE
  134.     IF command[]=0 THEN Raise(ER_COML)
  135.     s:=command
  136.     WHILE x:=s[]++
  137.       IF x="%"
  138.         x:=s[]
  139.         SELECT x
  140.           CASE "s"; ListAdd(prtab,[1],1)            /* %s = fullpath */
  141.           CASE "f"; ListAdd(prtab,NEW [work],1); s[]:="s"    /* %f = work     */
  142.           CASE "r"; ListAdd(prtab,NEW [work2],1); s[]:="s"    /* %r = work2    */
  143.           DEFAULT; s[-1]:=" "
  144.         ENDSELECT
  145.       ENDIF
  146.     ENDWHILE
  147.   ENDIF
  148.   dir:=args[ARG_DIR]
  149.   IF dir THEN StrCopy(dirw,dir,ALL)
  150.   lock:=Lock(dirw,-2)
  151.   IF lock                  /* if yes, the prob. dir, else wildcard */
  152.     IF Examine(lock,fib) AND (fib.direntrytype>0)
  153.       AddPart(dirw,'#?',100)
  154.     ENDIF
  155.     UnLock(lock)
  156.   ENDIF
  157.   recdir(dirw)
  158.   Raise(ER_NONE)
  159. EXCEPT
  160.   IF rdargs THEN FreeArgs(rdargs)
  161.   IF utilitybase THEN CloseLibrary(utilitybase)
  162.   SELECT exception
  163.     CASE ER_BADARGS;            WriteF('Bad Arguments for D!\n')
  164.     CASE ER_MEM;                WriteF('No mem!\n')
  165.     CASE ER_COML;               WriteF('No commandline specified\n')
  166.     CASE ER_ITARG;              WriteF('Illegal target\n')
  167.     CASE ER_UTIL;               WriteF('Could not open "utility.library" v37\n')
  168.     CASE ERROR_BREAK;           WriteF('User terminated D\n')
  169.     CASE ERROR_BUFFER_OVERFLOW; WriteF('Internal error\n')
  170.     DEFAULT;                    PrintFault(exception,'Dos Error')
  171.   ENDSELECT
  172. ENDPROC
  173.  
  174. PROC recdir(dirr) HANDLE
  175.   DEF er,i:PTR TO fileinfoblock,size=0,anchor=NIL:PTR TO anchorpath,fullpath,
  176.       flist=NIL,first,entries=0,sortdone,next,nnext,prev,ascii,x,y,flist2=NIL,
  177.       esc1,esc2,ds:PTR TO LONG,isfirst=0
  178.   anchor:=New(SIZEOF anchorpath+MAXPATH)
  179.   anchor.breakbits:=4096
  180.   anchor.strlen:=MAXPATH-1
  181.   esc1:=IF ansif THEN '\e[1;32m' ELSE ''
  182.   esc2:=IF ansif THEN '\e[0;31m' ELSE ''
  183.   ds:=['\s\l\s[50]\s <dir>','\l\s[47] \r\d[8]','\s\l\s[30]\s <dir>','\l\s[27] \r\d[8]','\s\l\s[19]\s <dir>','\l\s[17] \r\d[7]']
  184.   er:=MatchFirst(dirr,anchor)            /* collect all strings */
  185.   WHILE er=0
  186.     fullpath:=anchor+SIZEOF anchorpath
  187.     i:=anchor.info
  188.     ascii:=IF fullf THEN fullpath ELSE i.filename
  189.     IF i.direntrytype>0 THEN StringF(work,ds[col-1*2],esc1,ascii,esc2) ELSE StringF(work,ds[col-1*2+1],ascii,i.size)
  190.     IF IF i.direntrytype>0 THEN dirsf ELSE filesf
  191.       first:=String(EstrLen(work))
  192.       StrCopy(first,work,ALL)
  193.       flist:=Link(first,flist)
  194.       INC entries
  195.     ENDIF
  196.     IF i.direntrytype<0 THEN size:=size+i.size
  197.     IF (i.direntrytype<0) AND comf        /* execute commandline */
  198.       ListCopy(prcopy,prtab,ALL)
  199.       IF comf THEN MapList({x},prcopy,prcopy,`IF x=1 THEN fullpath ELSE x)
  200.       StrCopy(work,fullpath,ALL)
  201.       x:=InStr(work,'.',0)
  202.       IF x<>-1 THEN SetStr(work,x)        /* find f% */
  203.       IF target
  204.         StrCopy(work2,target,ALL)
  205.         x:=work; y:=dirw        /* was dirr */
  206.         WHILE x[]++=y[]++ DO NOP
  207.         DEC x
  208.         StrAdd(work2,x,ALL)            /* find r% */
  209.       ELSE
  210.         StrCopy(work2,work,ALL)
  211.       ENDIF
  212.       IF isfirst++=0
  213.         StrCopy(workdir,work2,ALL)        /* see if makedir is needed */
  214.         SetStr(workdir,PathPart(work2)-work2)
  215.         x:=Lock(workdir,-2)
  216.         IF x THEN UnLock(x) ELSE WriteF('makedir \s\n',workdir)
  217.       ENDIF
  218.       Flush(stdout); VfPrintf(stdout,command,prcopy); Flush(stdout)
  219.       WriteF('\n')
  220.     ENDIF
  221.     IF recf AND (i.direntrytype>0)        /* do recursion(=tail) */
  222.       x:=StrLen(fullpath)
  223.       IF x+5<MAXPATH THEN CopyMem('/#?',fullpath+x,4)
  224.       size:=size+recdir(fullpath)
  225.       fullpath[x]:=0
  226.     ENDIF
  227.     er:=MatchNext(anchor)
  228.   ENDWHILE
  229.   IF er<>ERROR_NO_MORE_ENTRIES THEN Raise(er)
  230.   MatchEnd(anchor)
  231.   Dispose(anchor)
  232.   anchor:=NIL
  233.   flist:=Link(String(1),flist)
  234.   IF entries>2 AND sortf
  235.     REPEAT
  236.       sortdone:=TRUE                /* sort dirlist */
  237.       prev:=first:=flist
  238.       WHILE first:=Next(first)
  239.         IF next:=Next(first)
  240.           IF Stricmp(first,next)>0
  241.             nnext:=Next(next)
  242.             Link(prev,first:=Link(next,Link(first,nnext)))
  243.             sortdone:=FALSE
  244.           ENDIF
  245.         ENDIF
  246.         CtrlC()
  247.         prev:=first
  248.       ENDWHILE
  249.     UNTIL sortdone
  250.   ENDIF
  251.   IF col>1                    /* put dirlist in columns */
  252.     x:=entries/col
  253.     IF x*col<entries THEN INC x
  254.     first:=Next(flist)
  255.     next:=Forward(first,x)
  256.     nnext:=IF col=3 THEN Forward(next,x) ELSE NIL
  257.     flist2:=Link(String(1),flist2)
  258.     prev:=flist2
  259.     WHILE first AND (x-->=0)
  260.       StrCopy(work,first,ALL)
  261.       IF next
  262.         StrAdd(work,' ',1)
  263.         StrAdd(work,next,ALL)
  264.         IF nnext
  265.           StrAdd(work,' ',1)
  266.           StrAdd(work,nnext,ALL)
  267.         ENDIF
  268.       ENDIF
  269.       ascii:=String(EstrLen(work))
  270.       StrCopy(ascii,work,ALL)
  271.       Link(prev,prev:=ascii)
  272.       first:=Next(first)
  273.       IF next THEN next:=Next(next)
  274.       IF nnext THEN nnext:=Next(nnext)
  275.     ENDWHILE
  276.     DisposeLink(flist)
  277.     flist:=flist2
  278.   ENDIF
  279.   IF comf=FALSE                        /* display dir */
  280.     IF dirno THEN WriteF('\n')
  281.     WriteF(IF ansif THEN '\e[1mDirectory of: "\s"\e[0m\n' ELSE 'Directory of: "\s"\n',dirr)
  282.   ENDIF
  283.   first:=flist
  284.   WHILE first:=Next(first)
  285.     WriteF('\s\n',first)
  286.     CtrlC()
  287.   ENDWHILE
  288.   IF sizef THEN WriteF('BYTE SIZE: \d\n',size)
  289.   DisposeLink(flist)
  290.   INC dirno
  291. EXCEPT                                  /* nested exception handlers! */
  292.   IF anchor THEN MatchEnd(anchor)
  293.   Raise(exception)  /* this way, we call _all_ handlers in the recursion  */
  294. ENDPROC size        /* and thus calling MatchEnd() on all hanging anchors */
  295.