mirror of
git://git.psyc.eu/libpsyc
synced 2024-08-15 03:19:02 +00:00
114 lines
3.2 KiB
C
114 lines
3.2 KiB
C
#include "psyc/lib.h"
|
|
|
|
int psyc_inherits(char* sho, size_t slen,
|
|
char* lon, size_t llen) {
|
|
|
|
// this allows to pass zero-terminated strings instead of providing
|
|
// the length.. but we would be faster here if we expected the callee
|
|
// to always use the PSYC_C2ARG() macro instead. additionally, the
|
|
// empty string would then be fully supported (in case you want that)
|
|
if (!slen) slen = strlen(sho);
|
|
if (!llen) llen = strlen(lon);
|
|
|
|
if (slen == 0 || *sho != '_' ||
|
|
llen == 0 || *lon != '_') {
|
|
P1(("Please use long format keywords (compact ones would be faster, I know..)\n"))
|
|
return -2;
|
|
}
|
|
|
|
if (slen > llen) {
|
|
P1(("The long string is shorter than the short one.\n"))
|
|
return -3;
|
|
}
|
|
|
|
if (!strncmp(sho, lon, slen)) {
|
|
/* according to PSYC spec we have hereby already proved
|
|
* inheritance. the following check is optional!
|
|
*/
|
|
if (llen > slen && lon[slen] != '_') {
|
|
/* It is illegal to introduce a keyword family
|
|
* that starts just like an existing one. Since
|
|
* _failure exists, you can't use _fail. But
|
|
* implementations are not required to recognize
|
|
* that.
|
|
*/
|
|
P1(("Illegal choice of keyword names!\n"))
|
|
return -4;
|
|
}
|
|
return 0;
|
|
}
|
|
P4(("%*s does not inherit from %*s.\n", llen, lon, slen, sho))
|
|
return 1;
|
|
}
|
|
|
|
int psyc_matches(char* sho, size_t slen,
|
|
char* lon, size_t llen) {
|
|
char *s, *l, *se, *le;
|
|
|
|
if (!slen) slen = strlen(sho);
|
|
if (!llen) llen = strlen(lon);
|
|
|
|
if (slen == 0 || *sho != '_' ||
|
|
llen == 0 || *lon != '_') {
|
|
P1(("Please use long format keywords (compact ones would be faster, I know..)\n"))
|
|
return -2;
|
|
}
|
|
|
|
if (slen > llen) {
|
|
P1(("The long string is shorter than the short one.\n"))
|
|
return -3;
|
|
}
|
|
|
|
if (slen == llen) {
|
|
if (!strncmp(sho, lon, slen)) {
|
|
P1(("Identical arguments.\n"))
|
|
return 0;
|
|
}
|
|
P1(("Same length but different.\nNo match, but they could be related or have a common type.\n"))
|
|
return -4;
|
|
}
|
|
P3(("# psyc_matches short '%*s' in long '%*s' ?\n", slen, sho, llen, lon))
|
|
|
|
se = sho+slen;
|
|
le = lon+llen;
|
|
sho++; lon++; slen--; llen--;
|
|
while(*sho && sho < se) {
|
|
P3(("# comparing short '%*s' (%d)\n", slen, sho, slen))
|
|
unless (s = memchr(sho, '_', slen)) s = se;
|
|
P4(("# sho goes '%c' and lon goes '%c'\n", *sho, *lon))
|
|
while(*lon && lon < le) {
|
|
P3(("# against long '%*s' (%d)\n", llen, lon, llen))
|
|
unless (l = memchr(lon, '_', llen)) l = le;
|
|
P3(("# %d == %d && !strncmp '%*s', '%*s'\n", s-sho, l-lon, s-sho, sho, s-sho, lon))
|
|
if (l-lon == s-sho && !strncmp(sho, lon, s-sho)) goto foundone;
|
|
P4(("# failed\n"))
|
|
llen -= l-lon + 1;
|
|
lon = ++l;
|
|
}
|
|
goto failed;
|
|
foundone:
|
|
P3(("# found %d of short '%*s' and long '%*s'\n", s-sho, s-sho, sho, s-sho, lon))
|
|
llen -= l-lon;
|
|
slen -= s-sho;
|
|
sho = ++s;
|
|
lon = ++l;
|
|
}
|
|
return 0;
|
|
failed:
|
|
P4(("No, they don't match.\n"))
|
|
return 1;
|
|
}
|
|
|
|
#ifdef CMDTOOL
|
|
int main(int argc, char **argv) {
|
|
if (argc != 3) {
|
|
printf("Usage: %s <short> <long>\n\nExample: %s _failure_delivery _failure_unsuccessful_delivery_death\n", argv[0], argv[0]);
|
|
return -1;
|
|
}
|
|
if (psyc_matches(argv[1], 0, argv[2], 0) == 0)
|
|
printf("Yes, %s matches %s!\n", argv[1], argv[2]);
|
|
if (psyc_inherits(argv[1], 0, argv[2], 0) == 0)
|
|
printf("Yes, %s inherits from %s!\n", argv[2], argv[1]);
|
|
}
|
|
#endif
|