156160Sru/* info-utils.c -- miscellanous. 2146515Sru $Id: info-utils.c,v 1.4 2004/04/11 17:56:45 karl Exp $ 321495Sjmacd 4146515Sru Copyright (C) 1993, 1998, 2003, 2004 Free Software Foundation, Inc. 521495Sjmacd 621495Sjmacd This program is free software; you can redistribute it and/or modify 721495Sjmacd it under the terms of the GNU General Public License as published by 821495Sjmacd the Free Software Foundation; either version 2, or (at your option) 921495Sjmacd any later version. 1021495Sjmacd 1121495Sjmacd This program is distributed in the hope that it will be useful, 1221495Sjmacd but WITHOUT ANY WARRANTY; without even the implied warranty of 1321495Sjmacd MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1421495Sjmacd GNU General Public License for more details. 1521495Sjmacd 1621495Sjmacd You should have received a copy of the GNU General Public License 1721495Sjmacd along with this program; if not, write to the Free Software 1821495Sjmacd Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 1921495Sjmacd 20146515Sru Originally written by Brian Fox (bfox@ai.mit.edu). */ 2121495Sjmacd 2242660Smarkm#include "info.h" 2321495Sjmacd#include "info-utils.h" 2421495Sjmacd#if defined (HANDLE_MAN_PAGES) 2521495Sjmacd# include "man.h" 2621495Sjmacd#endif /* HANDLE_MAN_PAGES */ 2721495Sjmacd 2821495Sjmacd/* When non-zero, various display and input functions handle ISO Latin 2921495Sjmacd character sets correctly. */ 3056160Sruint ISO_Latin_p = 1; 3121495Sjmacd 3221495Sjmacd/* Variable which holds the most recent filename parsed as a result of 3321495Sjmacd calling info_parse_xxx (). */ 3421495Sjmacdchar *info_parsed_filename = (char *)NULL; 3521495Sjmacd 3621495Sjmacd/* Variable which holds the most recent nodename parsed as a result of 3721495Sjmacd calling info_parse_xxx (). */ 3821495Sjmacdchar *info_parsed_nodename = (char *)NULL; 3921495Sjmacd 40146515Sru/* Variable which holds the most recent line number parsed as a result of 41146515Sru calling info_parse_xxx (). */ 42146515Sruint info_parsed_line_number = 0; 43146515Sru 4421495Sjmacd/* Functions to remember a filename or nodename for later return. */ 45146515Srustatic void save_filename (char *filename); 46146515Srustatic void saven_filename (char *filename, int len); 47146515Srustatic void save_nodename (char *nodename); 48146515Srustatic void saven_nodename (char *nodename, int len); 4921495Sjmacd 5021495Sjmacd/* How to get a reference (either menu or cross). */ 51146515Srustatic REFERENCE **info_references_internal (char *label, 52146515Sru SEARCH_BINDING *binding); 5321495Sjmacd 5421495Sjmacd/* Parse the filename and nodename out of STRING. If STRING doesn't 5521495Sjmacd contain a filename (i.e., it is NOT (FILENAME)NODENAME) then set 5621495Sjmacd INFO_PARSED_FILENAME to NULL. If second argument NEWLINES_OKAY is 5721495Sjmacd non-zero, it says to allow the nodename specification to cross a 5821495Sjmacd newline boundary (i.e., only `,', `.', or `TAB' can end the spec). */ 5921495Sjmacdvoid 60146515Sruinfo_parse_node (char *string, int newlines_okay) 6121495Sjmacd{ 6221495Sjmacd register int i = 0; 6321495Sjmacd 6421495Sjmacd /* Default the answer. */ 6521495Sjmacd save_filename ((char *)NULL); 6621495Sjmacd save_nodename ((char *)NULL); 6721495Sjmacd 6821495Sjmacd /* Special case of nothing passed. Return nothing. */ 6921495Sjmacd if (!string || !*string) 7021495Sjmacd return; 7121495Sjmacd 7221495Sjmacd string += skip_whitespace (string); 7321495Sjmacd 7421495Sjmacd /* Check for (FILENAME)NODENAME. */ 7521495Sjmacd if (*string == '(') 7621495Sjmacd { 7721495Sjmacd i = 0; 7821495Sjmacd /* Advance past the opening paren. */ 7921495Sjmacd string++; 8021495Sjmacd 8121495Sjmacd /* Find the closing paren. */ 8221495Sjmacd while (string[i] && string[i] != ')') 8342660Smarkm i++; 8421495Sjmacd 8521495Sjmacd /* Remember parsed filename. */ 8621495Sjmacd saven_filename (string, i); 8721495Sjmacd 8821495Sjmacd /* Point directly at the nodename. */ 8921495Sjmacd string += i; 9021495Sjmacd 9121495Sjmacd if (*string) 9242660Smarkm string++; 9321495Sjmacd } 9421495Sjmacd 9521495Sjmacd /* Parse out nodename. */ 9621495Sjmacd i = skip_node_characters (string, newlines_okay); 9721495Sjmacd saven_nodename (string, i); 9821495Sjmacd canonicalize_whitespace (info_parsed_nodename); 9921495Sjmacd if (info_parsed_nodename && !*info_parsed_nodename) 10021495Sjmacd { 10121495Sjmacd free (info_parsed_nodename); 10221495Sjmacd info_parsed_nodename = (char *)NULL; 10321495Sjmacd } 104146515Sru 105146515Sru /* Parse ``(line ...)'' part of menus, if any. */ 106146515Sru { 107146515Sru char *rest = string + i; 108146515Sru 109146515Sru /* Advance only if it's not already at end of string. */ 110146515Sru if (*rest) 111146515Sru rest++; 112146515Sru 113146515Sru /* Skip any whitespace first, and then a newline in case the item 114146515Sru was so long to contain the ``(line ...)'' string in the same 115146515Sru physical line. */ 116146515Sru while (whitespace(*rest)) 117146515Sru rest++; 118146515Sru if (*rest == '\n') 119146515Sru { 120146515Sru rest++; 121146515Sru while (whitespace(*rest)) 122146515Sru rest++; 123146515Sru } 124146515Sru 125146515Sru /* Are we looking at an opening parenthesis? That can only mean 126146515Sru we have a winner. :) */ 127146515Sru if (strncmp (rest, "(line ", strlen ("(line ")) == 0) 128146515Sru { 129146515Sru rest += strlen ("(line "); 130146515Sru info_parsed_line_number = strtol (rest, NULL, 0); 131146515Sru } 132146515Sru else 133146515Sru info_parsed_line_number = 0; 134146515Sru } 13521495Sjmacd} 13621495Sjmacd 13721495Sjmacd/* Return the node addressed by LABEL in NODE (usually one of "Prev:", 13821495Sjmacd "Next:", "Up:", "File:", or "Node:". After a call to this function, 13921495Sjmacd the global INFO_PARSED_NODENAME and INFO_PARSED_FILENAME contain 14021495Sjmacd the information. */ 14121495Sjmacdvoid 142146515Sruinfo_parse_label (char *label, NODE *node) 14321495Sjmacd{ 14421495Sjmacd register int i; 14521495Sjmacd char *nodeline; 14621495Sjmacd 14721495Sjmacd /* Default answer to failure. */ 14821495Sjmacd save_nodename ((char *)NULL); 14921495Sjmacd save_filename ((char *)NULL); 15021495Sjmacd 15121495Sjmacd /* Find the label in the first line of this node. */ 15221495Sjmacd nodeline = node->contents; 15321495Sjmacd i = string_in_line (label, nodeline); 15421495Sjmacd 15521495Sjmacd if (i == -1) 15621495Sjmacd return; 15721495Sjmacd 15821495Sjmacd nodeline += i; 15921495Sjmacd nodeline += skip_whitespace (nodeline); 16021495Sjmacd info_parse_node (nodeline, DONT_SKIP_NEWLINES); 16121495Sjmacd} 16221495Sjmacd 16321495Sjmacd/* **************************************************************** */ 16442660Smarkm/* */ 16542660Smarkm/* Finding and Building Menus */ 16642660Smarkm/* */ 16721495Sjmacd/* **************************************************************** */ 16821495Sjmacd 16921495Sjmacd/* Return a NULL terminated array of REFERENCE * which represents the menu 17021495Sjmacd found in NODE. If there is no menu in NODE, just return a NULL pointer. */ 17121495SjmacdREFERENCE ** 172146515Sruinfo_menu_of_node (NODE *node) 17321495Sjmacd{ 17421495Sjmacd long position; 175146515Sru SEARCH_BINDING tmp_search; 17621495Sjmacd REFERENCE **menu = (REFERENCE **)NULL; 17721495Sjmacd 178146515Sru tmp_search.buffer = node->contents; 179146515Sru tmp_search.start = 0; 180146515Sru tmp_search.end = node->nodelen; 181146515Sru tmp_search.flags = S_FoldCase; 18221495Sjmacd 18321495Sjmacd /* Find the start of the menu. */ 184146515Sru position = search_forward (INFO_MENU_LABEL, &tmp_search); 18521495Sjmacd 18621495Sjmacd if (position == -1) 18721495Sjmacd return ((REFERENCE **) NULL); 18821495Sjmacd 18921495Sjmacd /* We have the start of the menu now. Glean menu items from the rest 19021495Sjmacd of the node. */ 191146515Sru tmp_search.start = position + strlen (INFO_MENU_LABEL); 192146515Sru tmp_search.start += skip_line (tmp_search.buffer + tmp_search.start); 193146515Sru tmp_search.start--; 194146515Sru menu = info_menu_items (&tmp_search); 19521495Sjmacd return (menu); 19621495Sjmacd} 19721495Sjmacd 19821495Sjmacd/* Return a NULL terminated array of REFERENCE * which represents the cross 19921495Sjmacd refrences found in NODE. If there are no cross references in NODE, just 20021495Sjmacd return a NULL pointer. */ 20121495SjmacdREFERENCE ** 202146515Sruinfo_xrefs_of_node (NODE *node) 20321495Sjmacd{ 204146515Sru SEARCH_BINDING tmp_search; 20521495Sjmacd 20621495Sjmacd#if defined (HANDLE_MAN_PAGES) 20721495Sjmacd if (node->flags & N_IsManPage) 20821495Sjmacd return (xrefs_of_manpage (node)); 20921495Sjmacd#endif 21021495Sjmacd 211146515Sru tmp_search.buffer = node->contents; 212146515Sru tmp_search.start = 0; 213146515Sru tmp_search.end = node->nodelen; 214146515Sru tmp_search.flags = S_FoldCase; 21521495Sjmacd 216146515Sru return (info_xrefs (&tmp_search)); 21721495Sjmacd} 21821495Sjmacd 21921495Sjmacd/* Glean menu entries from BINDING->buffer + BINDING->start until we 22021495Sjmacd have looked at the entire contents of BINDING. Return an array 22121495Sjmacd of REFERENCE * that represents each menu item in this range. */ 22221495SjmacdREFERENCE ** 223146515Sruinfo_menu_items (SEARCH_BINDING *binding) 22421495Sjmacd{ 22521495Sjmacd return (info_references_internal (INFO_MENU_ENTRY_LABEL, binding)); 22621495Sjmacd} 22721495Sjmacd 22821495Sjmacd/* Glean cross references from BINDING->buffer + BINDING->start until 22921495Sjmacd BINDING->end. Return an array of REFERENCE * that represents each 23021495Sjmacd cross reference in this range. */ 23121495SjmacdREFERENCE ** 232146515Sruinfo_xrefs (SEARCH_BINDING *binding) 23321495Sjmacd{ 23421495Sjmacd return (info_references_internal (INFO_XREF_LABEL, binding)); 23521495Sjmacd} 23621495Sjmacd 23721495Sjmacd/* Glean cross references or menu items from BINDING. Return an array 23821495Sjmacd of REFERENCE * that represents the items found. */ 23921495Sjmacdstatic REFERENCE ** 240146515Sruinfo_references_internal (char *label, SEARCH_BINDING *binding) 24121495Sjmacd{ 242146515Sru SEARCH_BINDING tmp_search; 24321495Sjmacd REFERENCE **refs = (REFERENCE **)NULL; 24421495Sjmacd int refs_index = 0, refs_slots = 0; 24521495Sjmacd int searching_for_menu_items = 0; 24621495Sjmacd long position; 24721495Sjmacd 248146515Sru tmp_search.buffer = binding->buffer; 249146515Sru tmp_search.start = binding->start; 250146515Sru tmp_search.end = binding->end; 251146515Sru tmp_search.flags = S_FoldCase | S_SkipDest; 25221495Sjmacd 25321495Sjmacd searching_for_menu_items = (strcasecmp (label, INFO_MENU_ENTRY_LABEL) == 0); 25421495Sjmacd 255146515Sru while ((position = search_forward (label, &tmp_search)) != -1) 25621495Sjmacd { 25721495Sjmacd int offset, start; 25821495Sjmacd char *refdef; 25921495Sjmacd REFERENCE *entry; 26021495Sjmacd 261146515Sru tmp_search.start = position; 262146515Sru tmp_search.start += skip_whitespace (tmp_search.buffer + tmp_search.start); 263146515Sru start = tmp_search.start - binding->start; 264146515Sru refdef = tmp_search.buffer + tmp_search.start; 26521495Sjmacd offset = string_in_line (":", refdef); 26621495Sjmacd 26721495Sjmacd /* When searching for menu items, if no colon, there is no 26842660Smarkm menu item on this line. */ 26921495Sjmacd if (offset == -1) 27042660Smarkm { 27142660Smarkm if (searching_for_menu_items) 27242660Smarkm continue; 27342660Smarkm else 27442660Smarkm { 27542660Smarkm int temp; 27621495Sjmacd 27742660Smarkm temp = skip_line (refdef); 27842660Smarkm offset = string_in_line (":", refdef + temp); 27942660Smarkm if (offset == -1) 28042660Smarkm continue; /* Give up? */ 28142660Smarkm else 28242660Smarkm offset += temp; 28342660Smarkm } 28442660Smarkm } 28521495Sjmacd 28621495Sjmacd entry = (REFERENCE *)xmalloc (sizeof (REFERENCE)); 28721495Sjmacd entry->filename = (char *)NULL; 28821495Sjmacd entry->nodename = (char *)NULL; 28921495Sjmacd entry->label = (char *)xmalloc (offset); 29021495Sjmacd strncpy (entry->label, refdef, offset - 1); 29121495Sjmacd entry->label[offset - 1] = '\0'; 29221495Sjmacd canonicalize_whitespace (entry->label); 29321495Sjmacd 29421495Sjmacd refdef += offset; 29521495Sjmacd entry->start = start; 29621495Sjmacd entry->end = refdef - binding->buffer; 29721495Sjmacd 29821495Sjmacd /* If this reference entry continues with another ':' then the 29942660Smarkm nodename is the same as the label. */ 30021495Sjmacd if (*refdef == ':') 30142660Smarkm { 30242660Smarkm entry->nodename = xstrdup (entry->label); 30342660Smarkm } 30421495Sjmacd else 30542660Smarkm { 30642660Smarkm /* This entry continues with a specific nodename. Parse the 30742660Smarkm nodename from the specification. */ 30821495Sjmacd 30942660Smarkm refdef += skip_whitespace_and_newlines (refdef); 31021495Sjmacd 31142660Smarkm if (searching_for_menu_items) 31242660Smarkm info_parse_node (refdef, DONT_SKIP_NEWLINES); 31342660Smarkm else 31442660Smarkm info_parse_node (refdef, SKIP_NEWLINES); 31521495Sjmacd 31642660Smarkm if (info_parsed_filename) 31742660Smarkm entry->filename = xstrdup (info_parsed_filename); 31821495Sjmacd 31942660Smarkm if (info_parsed_nodename) 32042660Smarkm entry->nodename = xstrdup (info_parsed_nodename); 321146515Sru 322146515Sru entry->line_number = info_parsed_line_number; 32342660Smarkm } 32421495Sjmacd 32521495Sjmacd add_pointer_to_array 32642660Smarkm (entry, refs_index, refs, refs_slots, 50, REFERENCE *); 32721495Sjmacd } 32821495Sjmacd return (refs); 32921495Sjmacd} 33021495Sjmacd 33156160Sru/* Get the entry associated with LABEL in REFERENCES. Return a pointer 33256160Sru to the ENTRY if found, or NULL. */ 33321495SjmacdREFERENCE * 334146515Sruinfo_get_labeled_reference (char *label, REFERENCE **references) 33521495Sjmacd{ 33621495Sjmacd register int i; 33721495Sjmacd REFERENCE *entry; 33821495Sjmacd 33921495Sjmacd for (i = 0; references && (entry = references[i]); i++) 34021495Sjmacd { 34121495Sjmacd if (strcmp (label, entry->label) == 0) 34242660Smarkm return (entry); 34321495Sjmacd } 34421495Sjmacd return ((REFERENCE *)NULL); 34521495Sjmacd} 34621495Sjmacd 34721495Sjmacd/* A utility function for concatenating REFERENCE **. Returns a new 34821495Sjmacd REFERENCE ** which is the concatenation of REF1 and REF2. The REF1 34921495Sjmacd and REF2 arrays are freed, but their contents are not. */ 35021495SjmacdREFERENCE ** 351146515Sruinfo_concatenate_references (REFERENCE **ref1, REFERENCE **ref2) 35221495Sjmacd{ 35321495Sjmacd register int i, j; 35421495Sjmacd REFERENCE **result; 35521495Sjmacd int size; 35621495Sjmacd 35721495Sjmacd /* With one argument passed as NULL, simply return the other arg. */ 35821495Sjmacd if (!ref1) 35921495Sjmacd return (ref2); 36021495Sjmacd else if (!ref2) 36121495Sjmacd return (ref1); 36221495Sjmacd 36321495Sjmacd /* Get the total size of the slots that we will need. */ 36421495Sjmacd for (i = 0; ref1[i]; i++); 36521495Sjmacd size = i; 36621495Sjmacd for (i = 0; ref2[i]; i++); 36721495Sjmacd size += i; 36821495Sjmacd 36921495Sjmacd result = (REFERENCE **)xmalloc ((1 + size) * sizeof (REFERENCE *)); 37021495Sjmacd 37121495Sjmacd /* Copy the contents over. */ 37221495Sjmacd for (i = 0; ref1[i]; i++) 37321495Sjmacd result[i] = ref1[i]; 37421495Sjmacd 37521495Sjmacd j = i; 37621495Sjmacd for (i = 0; ref2[i]; i++) 37721495Sjmacd result[j++] = ref2[i]; 37821495Sjmacd 37921495Sjmacd result[j] = (REFERENCE *)NULL; 38021495Sjmacd free (ref1); 38121495Sjmacd free (ref2); 38221495Sjmacd return (result); 38321495Sjmacd} 38421495Sjmacd 385116525Sru 386116525Sru 387116525Sru/* Copy a reference structure. Since we tend to free everything at 388116525Sru every opportunity, we don't share any points, but copy everything into 389116525Sru new memory. */ 390116525SruREFERENCE * 391146515Sruinfo_copy_reference (REFERENCE *src) 392116525Sru{ 393116525Sru REFERENCE *dest = xmalloc (sizeof (REFERENCE)); 394116525Sru dest->label = src->label ? xstrdup (src->label) : NULL; 395116525Sru dest->filename = src->filename ? xstrdup (src->filename) : NULL; 396116525Sru dest->nodename = src->nodename ? xstrdup (src->nodename) : NULL; 397116525Sru dest->start = src->start; 398116525Sru dest->end = src->end; 399116525Sru 400116525Sru return dest; 401116525Sru} 402116525Sru 403116525Sru 404116525Sru 40521495Sjmacd/* Free the data associated with REFERENCES. */ 40621495Sjmacdvoid 407146515Sruinfo_free_references (REFERENCE **references) 40821495Sjmacd{ 40921495Sjmacd register int i; 41021495Sjmacd REFERENCE *entry; 41121495Sjmacd 41221495Sjmacd if (references) 41321495Sjmacd { 41421495Sjmacd for (i = 0; references && (entry = references[i]); i++) 41542660Smarkm { 41642660Smarkm maybe_free (entry->label); 41742660Smarkm maybe_free (entry->filename); 41842660Smarkm maybe_free (entry->nodename); 41921495Sjmacd 42042660Smarkm free (entry); 42142660Smarkm } 42221495Sjmacd 42321495Sjmacd free (references); 42421495Sjmacd } 42521495Sjmacd} 42621495Sjmacd 42721495Sjmacd/* Search for sequences of whitespace or newlines in STRING, replacing 42821495Sjmacd all such sequences with just a single space. Remove whitespace from 42921495Sjmacd start and end of string. */ 43021495Sjmacdvoid 431146515Srucanonicalize_whitespace (char *string) 43221495Sjmacd{ 43321495Sjmacd register int i, j; 434146515Sru int len, whitespace_found, whitespace_loc = 0; 43521495Sjmacd char *temp; 43621495Sjmacd 43721495Sjmacd if (!string) 43821495Sjmacd return; 43921495Sjmacd 44021495Sjmacd len = strlen (string); 44121495Sjmacd temp = (char *)xmalloc (1 + len); 44221495Sjmacd 44321495Sjmacd /* Search for sequences of whitespace or newlines. Replace all such 44421495Sjmacd sequences in the string with just a single space. */ 44521495Sjmacd 44621495Sjmacd whitespace_found = 0; 44721495Sjmacd for (i = 0, j = 0; string[i]; i++) 44821495Sjmacd { 44921495Sjmacd if (whitespace_or_newline (string[i])) 45042660Smarkm { 45142660Smarkm whitespace_found++; 45242660Smarkm whitespace_loc = i; 45342660Smarkm continue; 45442660Smarkm } 45521495Sjmacd else 45642660Smarkm { 45742660Smarkm if (whitespace_found && whitespace_loc) 45842660Smarkm { 45942660Smarkm whitespace_found = 0; 46021495Sjmacd 46142660Smarkm /* Suppress whitespace at start of string. */ 46242660Smarkm if (j) 46342660Smarkm temp[j++] = ' '; 46442660Smarkm } 46521495Sjmacd 46642660Smarkm temp[j++] = string[i]; 46742660Smarkm } 46821495Sjmacd } 46921495Sjmacd 47021495Sjmacd /* Kill trailing whitespace. */ 47121495Sjmacd if (j && whitespace (temp[j - 1])) 47221495Sjmacd j--; 47321495Sjmacd 47421495Sjmacd temp[j] = '\0'; 47521495Sjmacd strcpy (string, temp); 47621495Sjmacd free (temp); 47721495Sjmacd} 47821495Sjmacd 47921495Sjmacd/* String representation of a char returned by printed_representation (). */ 48021495Sjmacdstatic char the_rep[10]; 48121495Sjmacd 48221495Sjmacd/* Return a pointer to a string which is the printed representation 48321495Sjmacd of CHARACTER if it were printed at HPOS. */ 48421495Sjmacdchar * 485146515Sruprinted_representation (unsigned char character, int hpos) 48621495Sjmacd{ 48721495Sjmacd register int i = 0; 48856160Sru int printable_limit = ISO_Latin_p ? 255 : 127; 489100513Sru 490100513Sru if (raw_escapes_p && character == '\033') 491100513Sru the_rep[i++] = character; 49256160Sru /* Show CTRL-x as ^X. */ 493100513Sru else if (iscntrl (character) && character < 127) 49421495Sjmacd { 49521495Sjmacd switch (character) 49642660Smarkm { 49742660Smarkm case '\r': 49842660Smarkm case '\n': 49942660Smarkm the_rep[i++] = character; 50042660Smarkm break; 50121495Sjmacd 50242660Smarkm case '\t': 50342660Smarkm { 50442660Smarkm int tw; 50521495Sjmacd 50642660Smarkm tw = ((hpos + 8) & 0xf8) - hpos; 50742660Smarkm while (i < tw) 50842660Smarkm the_rep[i++] = ' '; 50942660Smarkm } 51042660Smarkm break; 51121495Sjmacd 51242660Smarkm default: 51342660Smarkm the_rep[i++] = '^'; 51442660Smarkm the_rep[i++] = (character | 0x40); 51542660Smarkm } 51621495Sjmacd } 51756160Sru /* Show META-x as 0370. */ 51821495Sjmacd else if (character > printable_limit) 51921495Sjmacd { 52021495Sjmacd sprintf (the_rep + i, "\\%0o", character); 52121495Sjmacd i = strlen (the_rep); 52221495Sjmacd } 52356160Sru else if (character == DEL) 52456160Sru { 52556160Sru the_rep[i++] = '^'; 52656160Sru the_rep[i++] = '?'; 52756160Sru } 52821495Sjmacd else 52921495Sjmacd the_rep[i++] = character; 53021495Sjmacd 53156160Sru the_rep[i] = 0; 53221495Sjmacd 53356160Sru return the_rep; 53421495Sjmacd} 53521495Sjmacd 53621495Sjmacd 53721495Sjmacd/* **************************************************************** */ 53842660Smarkm/* */ 53942660Smarkm/* Functions Static To This File */ 54042660Smarkm/* */ 54121495Sjmacd/* **************************************************************** */ 54221495Sjmacd 54321495Sjmacd/* Amount of space allocated to INFO_PARSED_FILENAME via xmalloc (). */ 54421495Sjmacdstatic int parsed_filename_size = 0; 54521495Sjmacd 54621495Sjmacd/* Amount of space allocated to INFO_PARSED_NODENAME via xmalloc (). */ 54721495Sjmacdstatic int parsed_nodename_size = 0; 54821495Sjmacd 549146515Srustatic void save_string (char *string, char **string_p, int *string_size_p); 550146515Srustatic void saven_string (char *string, int len, char **string_p, 551146515Sru int *string_size_p); 55221495Sjmacd 55321495Sjmacd/* Remember FILENAME in PARSED_FILENAME. An empty FILENAME is translated 55421495Sjmacd to a NULL pointer in PARSED_FILENAME. */ 55521495Sjmacdstatic void 556146515Srusave_filename (char *filename) 55721495Sjmacd{ 55821495Sjmacd save_string (filename, &info_parsed_filename, &parsed_filename_size); 55921495Sjmacd} 56021495Sjmacd 56121495Sjmacd/* Just like save_filename (), but you pass the length of the string. */ 56221495Sjmacdstatic void 563146515Srusaven_filename (char *filename, int len) 56421495Sjmacd{ 56521495Sjmacd saven_string (filename, len, 56642660Smarkm &info_parsed_filename, &parsed_filename_size); 56721495Sjmacd} 56821495Sjmacd 56921495Sjmacd/* Remember NODENAME in PARSED_NODENAME. An empty NODENAME is translated 57021495Sjmacd to a NULL pointer in PARSED_NODENAME. */ 57121495Sjmacdstatic void 572146515Srusave_nodename (char *nodename) 57321495Sjmacd{ 57421495Sjmacd save_string (nodename, &info_parsed_nodename, &parsed_nodename_size); 57521495Sjmacd} 57621495Sjmacd 57721495Sjmacd/* Just like save_nodename (), but you pass the length of the string. */ 57821495Sjmacdstatic void 579146515Srusaven_nodename (char *nodename, int len) 58021495Sjmacd{ 58121495Sjmacd saven_string (nodename, len, 58242660Smarkm &info_parsed_nodename, &parsed_nodename_size); 58321495Sjmacd} 58421495Sjmacd 58521495Sjmacd/* Remember STRING in STRING_P. STRING_P should currently have STRING_SIZE_P 58621495Sjmacd bytes allocated to it. An empty STRING is translated to a NULL pointer 58721495Sjmacd in STRING_P. */ 58821495Sjmacdstatic void 589146515Srusave_string (char *string, char **string_p, int *string_size_p) 59021495Sjmacd{ 59121495Sjmacd if (!string || !*string) 59221495Sjmacd { 59321495Sjmacd if (*string_p) 59442660Smarkm free (*string_p); 59521495Sjmacd 59621495Sjmacd *string_p = (char *)NULL; 59721495Sjmacd *string_size_p = 0; 59821495Sjmacd } 59921495Sjmacd else 60021495Sjmacd { 601146515Sru if (strlen (string) >= (unsigned int) *string_size_p) 60242660Smarkm *string_p = (char *)xrealloc 60342660Smarkm (*string_p, (*string_size_p = 1 + strlen (string))); 60421495Sjmacd 60521495Sjmacd strcpy (*string_p, string); 60621495Sjmacd } 60721495Sjmacd} 60821495Sjmacd 60921495Sjmacd/* Just like save_string (), but you also pass the length of STRING. */ 61021495Sjmacdstatic void 611146515Srusaven_string (char *string, int len, char **string_p, int *string_size_p) 61221495Sjmacd{ 61321495Sjmacd if (!string) 61421495Sjmacd { 61521495Sjmacd if (*string_p) 61642660Smarkm free (*string_p); 61721495Sjmacd 61821495Sjmacd *string_p = (char *)NULL; 61921495Sjmacd *string_size_p = 0; 62021495Sjmacd } 62121495Sjmacd else 62221495Sjmacd { 62321495Sjmacd if (len >= *string_size_p) 62442660Smarkm *string_p = (char *)xrealloc (*string_p, (*string_size_p = 1 + len)); 62521495Sjmacd 62621495Sjmacd strncpy (*string_p, string, len); 62721495Sjmacd (*string_p)[len] = '\0'; 62821495Sjmacd } 62921495Sjmacd} 63021495Sjmacd 63121495Sjmacd/* Return a pointer to the part of PATHNAME that simply defines the file. */ 63221495Sjmacdchar * 633146515Srufilename_non_directory (char *pathname) 63421495Sjmacd{ 63556160Sru register char *filename = pathname + strlen (pathname); 63621495Sjmacd 63756160Sru if (HAVE_DRIVE (pathname)) 63856160Sru pathname += 2; 63921495Sjmacd 64056160Sru while (filename > pathname && !IS_SLASH (filename[-1])) 64156160Sru filename--; 64221495Sjmacd 64321495Sjmacd return (filename); 64421495Sjmacd} 64521495Sjmacd 64621495Sjmacd/* Return non-zero if NODE is one especially created by Info. */ 64721495Sjmacdint 648146515Sruinternal_info_node_p (NODE *node) 64921495Sjmacd{ 65021495Sjmacd#if defined (NEVER) 65121495Sjmacd if (node && 65221495Sjmacd (node->filename && !*node->filename) && 65321495Sjmacd !node->parent && node->nodename) 65421495Sjmacd return (1); 65521495Sjmacd else 65621495Sjmacd return (0); 65721495Sjmacd#else 65821495Sjmacd return ((node != (NODE *)NULL) && ((node->flags & N_IsInternal) != 0)); 65921495Sjmacd#endif /* !NEVER */ 66021495Sjmacd} 66121495Sjmacd 66221495Sjmacd/* Make NODE appear to be one especially created by Info. */ 66321495Sjmacdvoid 664146515Sruname_internal_node (NODE *node, char *name) 66521495Sjmacd{ 66621495Sjmacd if (!node) 66721495Sjmacd return; 66821495Sjmacd 66921495Sjmacd node->filename = ""; 67021495Sjmacd node->parent = (char *)NULL; 67121495Sjmacd node->nodename = name; 67221495Sjmacd node->flags |= N_IsInternal; 67321495Sjmacd} 67421495Sjmacd 67521495Sjmacd/* Return the window displaying NAME, the name of an internally created 67621495Sjmacd Info window. */ 67721495SjmacdWINDOW * 678146515Sruget_internal_info_window (char *name) 67921495Sjmacd{ 68021495Sjmacd WINDOW *win; 68121495Sjmacd 68221495Sjmacd for (win = windows; win; win = win->next) 68321495Sjmacd if (internal_info_node_p (win->node) && 68442660Smarkm (strcmp (win->node->nodename, name) == 0)) 68521495Sjmacd break; 68621495Sjmacd 68721495Sjmacd return (win); 68821495Sjmacd} 68956160Sru 69056160Sru/* Return a window displaying the node NODE. */ 69156160SruWINDOW * 692146515Sruget_window_of_node (NODE *node) 69356160Sru{ 69456160Sru WINDOW *win = (WINDOW *)NULL; 69556160Sru 69656160Sru for (win = windows; win; win = win->next) 69756160Sru if (win->node == node) 69856160Sru break; 69956160Sru 70056160Sru return (win); 70156160Sru} 702