/* rdflags.c -- Copyright 1994 Liam R. E. Quin. * All Rights Reserved. * This code is NOT in the public domain. * See the file COPYRIGHT for full details. * * $Id: rdflags.c,v 1.12 2001/05/31 03:50:13 liam Exp $ * * Turn a flag string sequence into a flag value. */ #include "globals.h" /* defines and declarations for database filenames */ #include "error.h" #include /* for fileinfo.h */ #ifndef FILE # include #endif #ifdef HAVE_STRING_H # include #else # include #endif #ifdef HAVE_STDLIB_H # include #else # include #endif #include "fileinfo.h" #include "wordinfo.h" #include "wordrules.h" #include "emalloc.h" #include "lqutil.h" #include "liblqtext.h" #include "lqtrace.h" /** Unix system calls that need declaring: **/ /** Unix/C Library Functions that need declaring: **/ /** lqtext library functions that need declaring: **/ /** Functions within this file that are used before being defined: **/ /** **/ /* * LQT_StringToFlags * Tracing * *

Tries to reverse the operation of LQT_FlagsToString. * In other words, LQT_StringToFlags takes a string which it assumes * to be a sequence of names of flags found in the given FlagNames * array, separated by the given constant string, and returns the * bitwise `or' of the Value members corresponding to the Names that * are found.

*

In addition, a leading + or - is used to indicate that the * following flags are to be added (with bitwise or) or removed * (usinbg bitwise and on their negation) from the result. * * a pointer to the first unconverted character in String, and the * actual value in Flagp * * LQT_StringToWordFlags * LQT_WordFlagsToString * */ API char * LQT_StringToFlags(String, Flagp, WordFlagNamePairArray, Separator) char *String; unsigned long *Flagp; t_FlagNamePair *WordFlagNamePairArray; char *Separator; { register char *p; int SeparatorLength = strlen(Separator); char *StartOfNextChunk; enum { AddValue, SubtractValue, SetValue } Action = SetValue; unsigned long Result = 0; unsigned long Pending = 0; if (!String) { *Flagp = 0; return String; } if (!*String) { *Flagp = (unsigned long) 0; return String; } for (p = StartOfNextChunk = String; *p; /*NULL*/) { char *EndOfChunk; t_FlagNamePair *wp; char *Candidate; int SawTrailingSeparator = 0; EndOfChunk = 0; if (*p == '+' || *p == '-' || *p == '=') { if (Pending) { switch (Action) { case AddValue: Result |= Pending; break; case SubtractValue: Result &= ~Pending; break; case SetValue: Result = Pending; break; } Pending = 0; } switch (*p) { case '+': Action = AddValue; break; case '-': Action = SubtractValue; break; case '=': Action = SetValue; break; default: Error(E_FATAL|E_BUG|E_INTERNAL, "%s: %d: unhandled case 0%o=%c in switch", *p, *p ); } /* skip over the character */ StartOfNextChunk = ++p; } /** Look for a possible flag string **/ Candidate = StartOfNextChunk; for (p = &StartOfNextChunk[1]; *p; p++) { if (STRNCMP(p, Separator, SeparatorLength) == 0) { EndOfChunk = &p[-1]; /* String = StartOfNextChunk; */ p = StartOfNextChunk = &p[SeparatorLength]; if (!*StartOfNextChunk) { SawTrailingSeparator = 1; /* oops */ } break; } else if (*p == '+' || *p == '-' || *p == '=') { EndOfChunk = &p[-1]; /* String = StartOfNextChunk; */ StartOfNextChunk = &p[1]; if (!*StartOfNextChunk) { SawTrailingSeparator = 1; /* oops */ } break; } } if (!*p) { EndOfChunk = &p[-1]; /* String = StartOfNextChunk; */ StartOfNextChunk = p; } /** if we didn't get one, we're done **/ if (!EndOfChunk) { if (Pending) { switch (Action) { case AddValue: Result |= Pending; break; case SubtractValue: Result &= ~Pending; break; case SetValue: Result = Pending; break; } } *Flagp = Result; return p; } /** for each known flag value: **/ for (wp = WordFlagNamePairArray; wp->Name; wp++) { /** if it matches, use the value and stop looking: **/ if (STRNCMP(wp->Name, Candidate, (EndOfChunk - Candidate) + 1)==0){ Pending |= wp->Value; break; } } if (!wp->Name) { /* error: unrecognised string */ return Candidate; } if (SawTrailingSeparator) { /* error: trailing garbage */ return &StartOfNextChunk[-1]; } } /* for */ if (Pending) { switch (Action) { case AddValue: Result |= Pending; break; case SubtractValue: Result &= ~Pending; break; case SetValue: Result = Pending; break; } } *Flagp = Result; #ifdef ASCIITRACE LQT_Trace(LQTRACE_DEBUG, "string to flags: [%s] -> %d / 0%o / 0x%x -> %s", String, Result, Result, Result, LQT_FlagsToString(Result, WordFlagNamePairArray, Separator) ); #endif return p; } /* * LQT_StringToWordFlags * Tracing * * Tries to reverse the operation of LQT_WordFlagsToString. * In other words, LQT_StringToWordFlags takes a string which it * assumes to be a sequence of names of flags as defined in the * header file wordrules.h separated by LQTpWordFlagSep (a comma), * and returns the * bitwise `or' of the Word Flags corresponding to the Names that * are found. * * a pointer to the first unconverted character in String, and the * actual value in Flagp * * LQT_StringToWordFlags * LQT_WordFlagsToString * */ API char * LQT_StringToWordFlags(db, String, Flagp) t_LQTEXT_Database *db; char *String; unsigned long *Flagp; { extern t_FlagNamePair LQTp_WordFlagArray[]; /* later, this will be included in the database structure */ return LQT_StringToFlags( String, Flagp, LQTp_WordFlagArray, LQTpWordFlagSep ); }