peter@sugar.UUCP (Peter da Silva) (08/03/87)
Whereas it is my fixed belief that conforming to the standards of an operating system be desirable, unless those standards are unusable, and... Whereas the Amiga CLI uses keyword flags to specify options and arguments (albeit not entirely uniformly: "opt a" on one command means "all" on another)... Whereas this standard is not UNIX-like, but is also not unweildy... I would like to request that someone who has already done some work along these lines (to avoid reinventing the wheel) provide a command parser in the spirit of getopt (perhaps even one that allows programs to run in both fashions). Failing this, I'd like to see if there's enough interest out there for me to do so. It would make a nice pair with my Workbench File Requestor... -- -- Peter da Silva `-_-' ...!seismo!soma!uhnix1!sugar!peter (I said, NO PHOTOS!)
pete@violet.berkeley.edu (08/22/87)
peter@sugar.UUCP (Peter da Silva) writes: > > Whereas it is my fixed belief that conforming to the standards of an > operating system be desirable, unless those standards are unusable, > and... > Whereas the Amiga CLI uses keyword flags to specify options and > arguments (albeit not entirely uniformly: "opt a" on one command > means "all" on another)... > ..... > I would like to request that someone who has already done some work along > these lines (to avoid reinventing the wheel) provide a command parser in > the spirit of getopt (perhaps even one that allows programs to run > in both fashions). Failing this, I'd like to see if there's enough interest > out there for me to do so. It would make a nice pair with my Workbench > File Requestor... > -- Peter da Silva `-_-' ...!seismo!soma!uhnix1!sugar!peter (I said, NO PHOTOS!) I'm not sure how relevant it is, but I've just finished a general purpose string and filename matching utility that extends the basic AmigaDOS-style matching considerably. This ended up with quite a few command line keywords (eleven at current count!) and these are almost trivially decoded using the pattern matching algorithm itself and a SINGLE pattern. The same method could be used by any program that didn't mind the space taken up by the match procedure. This might be a problem: the Lattice 3.10 object of this module takes up about 2600 bytes (with about 1.5K of stack space while matching is going on). I hope it will compile under Manx without trouble -- I've tried to keep to vanilla C -- and it probably would be shorter there, but eventually it is probably worth the trip to Assembly. In case you're interested, though, here's how it works. The key addition which lets you identify multiple keywords with a single match is the "slice-mark" character. The procedure returns a vector indicating those slice-marks encountered in a successful match; the position of the slice both in the pattern and the matched string is returned. As you know where a mark is in the supplied pattern, you can directly identify which keyword it is associated with, and use a "switch" statement to select the action. ++++++++++ Here is an abbreviated version of the command line argument checking function in the program: /* * Argument Recognition Section * * checkarg -- matches the argument against argpat, and takes the * appropriate action if there is a match. * Note how it uses the slicing information returned * by SMatch as a convenient way of determining the * actual meaning of the argument. */ /* First, here's the pattern with the keywords...*/ char argpat[] = "NOCASE^|CASE^|(FILES|F)^|STRING^"; /* etc....*/ /* these are the positions of the corresponding slices in the pattern: */ #define NOCASE 7 #define CASE 13 #define FILES 24 #define STRING 32 /* the auxiliary vector for the pattern -- filled by CmplPat: */ UBYTE argaux[33]; /* lengthen as necessary! */ checkarg(pargc,pargv) int *pargc; char **pargv[]; { char argcuts[33], upperarg[256], *cutp = argcuts; if (!*pargc) return FALSE; /* don't run off the end... */ CmplPat(argpat, argaux); /* ...pure laziness -- I could use a precompiled pattern */ uppercase(**pargv, upperarg); /* I used my own short procedure to change strings to upper case */ if (SMatch(argpat, argaux, upperarg, argcuts)) { while (!cutp[1]) cutp += 2; /* skip phony subpatterns (e.g. "F") */ /* the above is necessary for reasons I won't explain here */ switch((int)(*cutp)) { case NOCASE: casesens = FALSE; break; case CASE: casesens = TRUE; break; case FILES: matchmode = MATCH_NAMES; break; case STRING: matchmode = MATCH_IMMED; break; /*... more as needed... (and as heavy-duty as you want...) */ } (*pargv)++; /* move past this argument */ (*pargc)--; return TRUE; /* say we found a keyword */ } return FALSE; /* not a keyword -- do something else */ } Some short explanation regarding the pattern match: A pattern must first be "compiled" ( with CmplPat() ) to generate an auxiliary control vector ("argaux" in this case). A given pattern only has to be compiled once, and in fact it is fairly trivial to work out the control vector of a pattern like that by hand, but because I was changing it often and the overhead is negligible here, I just do it each time the function is called. The match routine -- called SMatch() here to distinguish it from a simpler version that lacks slicing -- takes as arguments the pattern, its auxiliary vector, the string to be matched, and another vector in which the slice references will be returned. For each reference you get a pair of bytes in the slice vector ("argcuts"); the first is the position of the mark in the pattern (the first character is 1, not 0); the second is the position in the matched string. We don't care about the latter here, except there are some situations in which you can see a phony slice with a zero string position. The mysterious "while" statement takes care of that. There's an overall limit of 255 characters in the pattern, because byte size offsets are used. Beyond that you'd just have to add a second pattern and match call. +++++++++++ The match algorithm was developed from Martin Richards' BCPL original, and I consider it to be in the public domain. It's a bit long to post here though (at least to my tastes). The whole String Matching Utility package is certainly too long. If I believed in the reality of comp.sources.amiga I'd send it there, but you'll probably see it first on a Fish Disk. I hope to get it off to him RSN. BTW the whole thing was sparked by my desire a) to have a better string search program that would be flexible in the kind of output it generated, and b) to be able to do "impossible" things like: rename #?.c as old_#?.c (!!) The Utility handles both these areas quite well for a first shot (I think!), though its command lines can get a little intricate -- it's best within command scripts. -- Pete Goodeve --