void ExecuteAction( STM_StateMachine *sm, int actionIdx, const char *actionStr ) { /* * ActionIdx 0 is reserved as the 'do-nothing' action, or idle action * (but only if one wasn't provided by the user). */ if ( actionIdx > 0 ) { ASSERT( actionIdx < sm->numActions ); if ( sm->action != NULL ) { ASSERT( sm->actionProc == NULL ); DBG_ACTION( "STM %s: Calling %s action %s\n", sm->name, actionStr, sm->actionStr[ actionIdx ] ); (*sm->action[ actionIdx ])(); } else { ASSERT( sm->actionProc != NULL ); DBG_ACTION( "STM %s: Invoking %s action %s\n", sm->name, actionStr, sm->actionStr[ actionIdx ] ); (*sm->actionProc)( sm, actionIdx ); } } } // ExecuteAction
/* ------------------------------------------------------------------------ @NAME : bt_free_name() @INPUT : name @OUTPUT : @RETURNS : @DESCRIPTION: Frees up any memory allocated for a bt_name structure (namely, the `tokens' field [a bt_stringlist structure, this freed with bt_free_list()] and the structure itself.) @CALLS : bt_free_list() @CALLERS : anyone (exported) @CREATED : 1997/11/14, GPW @MODIFIED : -------------------------------------------------------------------------- */ void bt_free_name (bt_name * name) { DBG_ACTION (2, printf ("bt_free_name(): freeing name %p " "(%d tokens, string=%p (%s), last[0]=%s)\n", name, name->tokens->num_items, name->tokens->string, name->tokens->string, name->parts[BTN_LAST][0])); bt_free_list (name->tokens); free (name); DBG_ACTION (2, printf ("bt_free_name(): done, everything freed\n")); }
/* ------------------------------------------------------------------------ @NAME : bt_purify_string() @INOUT : instr @INPUT : options @OUTPUT : @RETURNS : instr - same as input string, but modified in place @DESCRIPTION: "Purifies" a BibTeX string. This consists of copying alphanumeric characters, converting hyphens and ties to space, copying spaces, and skipping everything else. (Well, almost -- special characters are handled specially, of course. Basically, accented letters have the control sequence skipped, while foreign letters have the control sequence preserved in a reasonable manner. See purify_special_char() for details.) @CALLS : purify_special_char() @CALLERS : @CREATED : 1997/10/19, GPW @MODIFIED : -------------------------------------------------------------------------- */ void bt_purify_string (char * string, btshort options) { int src, /* both indeces into string */ dst; int depth; /* brace depth in string */ unsigned orig_len; /* * Since purification always copies or deletes chars, outstr will * be no longer than string -- so nothing fancy is required to put * an upper bound on its eventual size. */ depth = 0; src = 0; dst = 0; orig_len = strlen (string); DBG_ACTION (1, printf ("bt_purify_string(): input = %p (%s)\n", string, string)); while (string[src] != (char) 0) { DBG_ACTION (2, printf (" next: >%c<: ", string[src])); switch (string[src]) { case '~': /* "separator" characters -- */ case '-': /* replaced with space */ case ' ': /* and copy an actual space */ string[dst++] = ' '; src++; DBG_ACTION (2, printf ("replacing with space")); break; case '{': if (depth == 0 && string[src+1] == '\\') { DBG_ACTION (2, printf ("special char found")); purify_special_char (string, &src, &dst); } else { DBG_ACTION (2, printf ("ordinary open brace")); src++; } depth++; break; case '}': DBG_ACTION (2, printf ("close brace")); depth--; src++; break; default: if (isalnum (string[src])) /* any alphanumeric char -- */ { DBG_ACTION (2, printf ("alphanumeric -- copying")); string[dst++] = string[src++]; /* copy it */ } else /* anything else -- skip it */ { DBG_ACTION (2, printf ("non-separator, non-brace, non-alpha")); src++; } } /* switch string[src] */ DBG_ACTION (2, printf ("\n")); } /* while string[src] */ DBG_ACTION (1, printf ("bt_purify_string(): depth on exit: %d\n", depth)); string[dst] = (char) 0; assert (strlen (string) <= orig_len); } /* bt_purify_string() */
/* ------------------------------------------------------------------------ @NAME : bt_split_name() @INPUT : name filename line name_num @OUTPUT : @RETURNS : newly-allocated bt_name structure containing the four parts as token-lists @DESCRIPTION: Splits a name according to the BibTeX rules. There are actually two sets of rules: one for names with no commas, and one for names with 1 or 2 commas. (If a name has more than 2 commas, the extras are removed and it's treated as though it had just the first 2.) See split_simple_name() for the no-comma rules, and split_general_name() for the 1-or-2-commas rules. The bt_name structure returned can (and should) be freed with bt_free_name() when you no longer need it. @GLOBALS : @CALLS : @CALLERS : anyone (exported by library) @CREATED : 1997/05/14, Greg Ward @MODIFIED : @COMMENTS : The name-splitting code all implicitly assumes that the string being split has been post-processed to collapse whitespace in the BibTeX way. This means that it tends to dump core on such things as leading whitespace, or more than one space in a row inside the string. This could probably be alleviated with a call to bt_postprocess_string(), possibly preceded by a check for any of those occurences. Before doing that, though, I want to examine the code carefully to determine just what assumptions it makes -- so I can check/correct for all of them. -------------------------------------------------------------------------- */ bt_name * bt_split_name (char * name, char * filename, int line, int name_num) { name_loc loc; bt_stringlist * tokens; int comma_token[MAX_COMMAS]; int len; int num_commas; int first_lc, last_lc; bt_name * split_name; int i; DBG_ACTION (1, printf ("bt_split_name(): name=%p (%s)\n", name, name)) split_name = (bt_name *) malloc (sizeof (bt_name)); if (name == NULL) { len = 0; } else { name = strdup (name); /* private copy that we may clobber */ len = strlen (name); } DBG_ACTION (1, printf ("bt_split_name(): split_name=%p\n", split_name)) if (len == 0) /* non-existent or empty string? */ { for (i = 0; i < BT_MAX_NAMEPARTS; i++) { split_name->parts[i] = NULL; split_name->part_len[i] = 0; } return split_name; } loc.filename = filename; /* so called functions can generate */ loc.line = line; /* decent warning messages */ loc.name_num = name_num; num_commas = find_commas (&loc, name, MAX_COMMAS); assert (num_commas <= MAX_COMMAS); DBG_ACTION (1, printf ("found %d commas: ", num_commas)) tokens = find_tokens (name, comma_token); #if DEBUG printf ("found %d tokens:\n", tokens->num_items); for (i = 0; i < tokens->num_items; i++) { printf (" %d: ", i); if (tokens->items[i]) /* non-empty token? */ { printf (">%s<\n", tokens->items[i]); } else { printf ("(empty)\n"); } } #endif #if DEBUG printf ("comma tokens: "); for (i = 0; i < num_commas; i++) printf ("%d ", comma_token[i]); printf ("\n"); #endif find_lc_tokens (tokens, &first_lc, &last_lc); #if DEBUG printf ("(first,last) lc tokens = (%d,%d)\n", first_lc, last_lc); #endif if (strlen (name) == 0) /* name now empty? */ { for (i = 0; i < BT_MAX_NAMEPARTS; i++) { split_name->parts[i] = NULL; split_name->part_len[i] = 0; } } else { split_name->tokens = tokens; if (num_commas == 0) /* no commas -- "simple" format */ { split_simple_name (&loc, split_name, first_lc, last_lc); } else { split_general_name (&loc, split_name, num_commas, comma_token, first_lc, last_lc); } } #if DEBUG printf ("bt_split_name(): returning structure %p\n", split_name); #endif return split_name; } /* bt_split_name() */