home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 4 / DATAFILE_PDCD4.iso / unix / armlinux / alpha / PARTITIONS / USR_GZ / usr / include / regexp.h < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-14  |  5.1 KB  |  221 lines

  1. /*
  2.  * regexp.h -- old-style regexp compile and step (emulated with POSIX regex)
  3.  * Copyright (C) 1993 Rick Sladkey <jrs@world.std.com>
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU Library Public License as published by
  7.  * the Free Software Foundation; either version 2, or (at your option)
  8.  * any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU Library Public License for more details.
  14.  */
  15.  
  16. /*
  17.  * Think really hard before you intentionally include this file.
  18.  * You should really be using the POSIX regex interface instead.
  19.  * This emulation file is intended solely for compiling old code.
  20.  *
  21.  * A program that uses this file must define six macros: INIT,
  22.  * GETC, PEEKC, UNGETC, RETURN, and ERROR.  This interface is
  23.  * so arcane that VMS hackers point at it in ridicule.
  24.  */
  25.  
  26. #ifndef _REGEXP_H
  27. #define _REGEXP_H
  28.  
  29. #include <sys/types.h>            /* regex.h needs size_t */
  30. #include <regex.h>            /* POSIX.2 regexp routines */
  31. #include <stdlib.h>            /* for malloc, realloc and free */
  32.  
  33. /*
  34.  * These three advertised external variables record state information
  35.  * for compile and step.  They are so gross, I'm choking as I write this.
  36.  */
  37. char *loc1;                /* the beginning of a match */
  38. char *loc2;                /* the end of a match */
  39. int circf;                /* current pattern begins with '^' */
  40.  
  41. /*
  42.  * These are the other variables mentioned in the regexp.h manpage.
  43.  * Since we don't emulate them (whatever they do), we want errors if
  44.  * they are referenced.  Therefore they are commented out here.
  45.  */
  46. #if 0
  47. char *locs;
  48. int sed;
  49. int nbra;
  50. #endif
  51.  
  52. /*
  53.  * We need to stuff a regex_t into an arbitrary buffer so align it.
  54.  * GCC make this easy.  For the others we have to guess.
  55.  */
  56. #ifdef __GNUC__
  57. #define __REGEX_T_ALIGN (__alignof__(regex_t))
  58. #else /* !__GNUC__ */
  59. #define __REGEX_T_ALIGN 8
  60. #endif /* !__GNUC__ */
  61.  
  62. #define __regex_t_align(p)                        \
  63.     ((regex_t *) ((((unsigned long) p) + __REGEX_T_ALIGN - 1)    \
  64.         / __REGEX_T_ALIGN * __REGEX_T_ALIGN))
  65.  
  66. /*
  67.  * We just slurp the whole pattern into a string and then compile
  68.  * it `normally'.  With this implementation we never use the PEEKC
  69.  * macro.  Please feel free to die laughing when we translate
  70.  * error symbols into hard-coded numbers.
  71.  */
  72. char *
  73. compile(char *instring, char *expbuf, char *endbuf, int eof)
  74. {
  75.     int __c;
  76.     int __len;
  77.     char *__buf;
  78.     int __buflen;
  79.     int __error;
  80.     regex_t *__preg;
  81.     INIT;
  82.  
  83.     __buflen = 128;
  84.     __buf = malloc(__buflen);
  85.     if (!__buf) {
  86.         ERROR(50);
  87.         return 0;
  88.     }
  89.     __len = 0;
  90.     circf = 0;
  91.     for (;;) {
  92.         __c = GETC();
  93.         if (__c == eof)
  94.             break;
  95.         if (__c == '\0' || __c == '\n') {
  96.             UNGETC(__c);
  97.             break;
  98.         }
  99.         if (__len + 2 > __buflen) {
  100.             __buflen *= 2;
  101.             __buf = realloc(__buf, __buflen);
  102.             if (!__buf) {
  103.                 ERROR(50);
  104.                 return 0;
  105.             }
  106.         }
  107.         if (__len == 0 && !circf && __c == '^')
  108.             circf = 1;
  109.         else
  110.             __buf[__len++] = __c;
  111.     }
  112.     if (__len == 0 && !circf) {
  113.         free(__buf);
  114.         ERROR(41);
  115.         return 0;
  116.     }
  117.     __buf[__len] = '\0';
  118.     if (endbuf <= expbuf + sizeof(regex_t)) {
  119.         free(__buf);
  120.         ERROR(50);
  121.         return 0;
  122.     }
  123.     __preg = __regex_t_align(expbuf);
  124.     __preg->buffer = (char *) (__preg + 1);
  125.     __preg->allocated = endbuf - (char *) __preg->buffer;
  126.     __error = regcomp(__preg, __buf, REG_NEWLINE);
  127.     free(__buf);
  128.     switch (__error) {
  129.     case 0:
  130.         break;
  131.     case REG_BADRPT:
  132.         __error = 36; /* poor fit */
  133.         break;
  134.     case REG_BADBR:
  135.         __error = 16;
  136.         break;
  137.     case REG_EBRACE:
  138.         __error = 44; /* poor fit */
  139.         break;
  140.     case REG_EBRACK:
  141.         __error = 49;
  142.         break;
  143.     case REG_ERANGE:
  144.         __error = 36; /* poor fit */
  145.         break;
  146.     case REG_ECTYPE:
  147.         __error = 36; /* poor fit */
  148.         break;
  149.     case REG_EPAREN:
  150.         __error = 42;
  151.         break;
  152.     case REG_ESUBREG:
  153.         __error = 36; /* poor fit */
  154.         break;
  155.     case REG_EEND:
  156.         __error = 36; /* poor fit */
  157.         break;
  158.     case REG_EESCAPE:
  159.         __error = 36;
  160.         break;
  161.     case REG_BADPAT:
  162.         __error = 36; /* poor fit */
  163.         break;
  164.     case REG_ESIZE:
  165.         __error = 50;
  166.         break;
  167.     case REG_ESPACE:
  168.         __error = 50;
  169.         break;
  170.     default:
  171.         __error = 36; /* as good as any */
  172.         break;
  173.     }
  174.     if (__error) {
  175.         ERROR(__error);
  176.         return 0;
  177.     }
  178.     RETURN((__preg->buffer + __preg->used));
  179. }
  180.  
  181. /*
  182.  * Note how we carefully emulate the gross `circf' hack.  Otherwise,
  183.  * this just looks like an ordinary matching call that records the
  184.  * starting and ending match positions.
  185.  */
  186. int
  187. step(char *string, char *expbuf)
  188. {
  189.     int __result;
  190.     regmatch_t __pmatch[1];
  191.  
  192.     __result = regexec(__regex_t_align(expbuf), string, 1, __pmatch, 0);
  193.     if (circf && __pmatch[0].rm_so != 0)
  194.         __result = REG_NOMATCH;
  195.     if (__result == 0) {
  196.         loc1 = string + __pmatch[0].rm_so;
  197.         loc2 = string + __pmatch[0].rm_eo;
  198.     }
  199.     return __result == 0;
  200. }
  201.  
  202. /*
  203.  * For advance we are only supposed to match at the beginning of the
  204.  * string.  You have to read the man page really carefully to find this
  205.  * one.  We'll match them kludge-for-kludge.
  206.  */
  207. int
  208. advance(char *string, char *expbuf)
  209. {
  210.     int __old_circf;
  211.     int __result;
  212.  
  213.     __old_circf = circf;
  214.     circf = 1;
  215.     __result = step(string, expbuf);
  216.     circf = __old_circf;
  217.     return __result;
  218. }
  219.  
  220. #endif /* _REGEXP_H */
  221.