+
+
+#ifdef MACOS_TRADITIONAL
+
+/* Replace the last occurrence of the pattern ":[^:]+::", e.g. ":lib::",
+ with a single ':', if possible. It is not an error, if the pattern
+ doesn't match (we return -1), but if there are two consecutive colons
+ '::', there must be a preceding ':[^:]+'. Hence, a volume path like
+ "HD::" is considered to be an error (we return 1), that is, it can't
+ be resolved. We return 0 on success.
+*/
+
+static short
+updir(char *path)
+{
+ char *pb, *pe, *lastchar;
+ char *bgn_mark, *end_mark;
+ char *f, *m, *b; /* front, middle, back */
+ size_t len;
+
+ len = strlen(path);
+ lastchar = path + (len-1);
+ b = lastchar;
+ m = lastchar-1;
+ f = lastchar-2;
+
+ /* find a '[^:]::' (e.g. b::) pattern ... */
+ while ( !( (*f != BG_SEP) && (*m == BG_SEP) && (*b == BG_SEP) )
+ && (f >= path)) {
+ f--;
+ m--;
+ b--;
+ }
+
+ if (f < path) { /* no (more) match */
+ return -1;
+ }
+
+ end_mark = b;
+
+ /* ... and now find its preceding colon ':' */
+ while ((*f != BG_SEP) && (f >= path)) {
+ f--;
+ }
+ if (f < path) {
+ /* No preceding colon found, must be a
+ volume path. We can't move up the
+ tree and that's an error */
+ return 1;
+ }
+ bgn_mark = f;
+
+ /* Shrink path, i.e. exclude all characters between
+ bgn_mark and end_mark */
+
+ pb = bgn_mark;
+ pe = end_mark;
+ while (*pb++ = *pe++) ;
+ return 0;
+}
+
+
+/* Resolve all updirs in pattern. */
+
+static short
+resolve_updirs(char *new_pattern)
+{
+ short err;
+
+ do {
+ err = updir(new_pattern);
+ } while (!err);
+ if (err == 1) {
+ return NO_UPDIR_ERR;
+ }
+ return 0;
+}
+
+
+/* Remove a trailing colon from the path, but only if it's
+ not a volume path (e.g. HD:) and not a path consisting
+ solely of colons. */
+
+static void
+remove_trColon(char *path)
+{
+ char *lastchar, *lc;
+
+ /* if path matches the pattern /:[^:]+:$/, we can
+ remove the trailing ':' */
+
+ lc = lastchar = path + (strlen(path) - 1);
+ if (*lastchar == BG_SEP) {
+ /* there's a trailing ':', there must be at least
+ one preceding char != ':' and a preceding ':' */
+ lc--;
+ if ((*lc != BG_SEP) && (lc >= path)) {
+ lc--;
+ } else {
+ return;
+ }
+ while ((*lc != BG_SEP) && (lc >= path)) {
+ lc--;
+ }
+ if (lc >= path) {
+ /* ... there's a preceding ':', we remove
+ the trailing colon */
+ *lastchar = BG_EOS;
+ }
+ }
+}
+
+
+/* With the GLOB_MARK flag on, we append a colon, if pathbuf
+ is a directory. If the directory name contains no colons,
+ e.g. 'lib', we can't simply append a ':', since this (e.g.
+ 'lib:') is not a valid (relative) path on Mac OS. Instead,
+ we add a leading _and_ trailing ':'. */
+
+static short
+glob_mark_Mac(Char *pathbuf, Char *pathend, Char *pathend_last)
+{
+ Char *p, *pe;
+ Boolean is_file = true;
+
+ /* check if pathbuf contains a ':',
+ i.e. is not a file name */
+ p = pathbuf;
+ while (*p != BG_EOS) {
+ if (*p == BG_SEP) {
+ is_file = false;
+ break;
+ }
+ p++;
+ }
+
+ if (is_file) {
+ if (pathend+2 > pathend_last) {
+ return (1);
+ }
+ /* right shift one char */
+ pe = p = pathend;
+ p--;
+ pathend++;
+ while (p >= pathbuf) {
+ *pe-- = *p--;
+ }
+ /* first char becomes a colon */
+ *pathbuf = BG_SEP;
+ /* append a colon */
+ *pathend++ = BG_SEP;
+ *pathend = BG_EOS;
+
+ } else {
+ if (pathend+1 > pathend_last) {
+ return (1);
+ }
+ *pathend++ = BG_SEP;
+ *pathend = BG_EOS;
+ }
+ return 0;
+}
+
+
+/* Return a FSSpec record for the specified volume
+ (borrowed from MacPerl.xs). */
+
+static OSErr
+GetVolInfo(short volume, Boolean indexed, FSSpec* spec)
+{
+ OSErr err; /* OSErr: 16-bit integer */
+ HParamBlockRec pb;
+
+ pb.volumeParam.ioNamePtr = spec->name;
+ pb.volumeParam.ioVRefNum = indexed ? 0 : volume;
+ pb.volumeParam.ioVolIndex = indexed ? volume : 0;
+
+ if (err = PBHGetVInfoSync(&pb))
+ return err;
+
+ spec->vRefNum = pb.volumeParam.ioVRefNum;
+ spec->parID = 1;
+
+ return noErr; /* 0 */
+}
+
+/* Extract a C name from a FSSpec. Note that there are
+ no leading or trailing colons. */
+
+static void
+name_f_FSSpec(StrFileName name, FSSpec *spec)
+{
+ unsigned char *nc;
+ const short len = spec->name[0];
+ short i;
+
+ /* FSSpec.name is a Pascal string,
+ convert it to C ... */
+ nc = name;
+ for (i=1; i<=len; i++) {
+ *nc++ = spec->name[i];
+ }
+ *nc = BG_EOS;
+}
+
+#endif /* MACOS_TRADITIONAL */