1 1.1 christos /* $NetBSD: info-utils.c,v 1.1.1.1 2016/01/14 00:11:29 christos Exp $ */ 2 1.1 christos 3 1.1 christos /* info-utils.c -- miscellanous. 4 1.1 christos Id: info-utils.c,v 1.4 2004/04/11 17:56:45 karl Exp 5 1.1 christos 6 1.1 christos Copyright (C) 1993, 1998, 2003, 2004 Free Software Foundation, Inc. 7 1.1 christos 8 1.1 christos This program is free software; you can redistribute it and/or modify 9 1.1 christos it under the terms of the GNU General Public License as published by 10 1.1 christos the Free Software Foundation; either version 2, or (at your option) 11 1.1 christos any later version. 12 1.1 christos 13 1.1 christos This program is distributed in the hope that it will be useful, 14 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 15 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 1.1 christos GNU General Public License for more details. 17 1.1 christos 18 1.1 christos You should have received a copy of the GNU General Public License 19 1.1 christos along with this program; if not, write to the Free Software 20 1.1 christos Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 1.1 christos 22 1.1 christos Originally written by Brian Fox (bfox (at) ai.mit.edu). */ 23 1.1 christos 24 1.1 christos #include "info.h" 25 1.1 christos #include "info-utils.h" 26 1.1 christos #if defined (HANDLE_MAN_PAGES) 27 1.1 christos # include "man.h" 28 1.1 christos #endif /* HANDLE_MAN_PAGES */ 29 1.1 christos 30 1.1 christos /* When non-zero, various display and input functions handle ISO Latin 31 1.1 christos character sets correctly. */ 32 1.1 christos int ISO_Latin_p = 1; 33 1.1 christos 34 1.1 christos /* Variable which holds the most recent filename parsed as a result of 35 1.1 christos calling info_parse_xxx (). */ 36 1.1 christos char *info_parsed_filename = (char *)NULL; 37 1.1 christos 38 1.1 christos /* Variable which holds the most recent nodename parsed as a result of 39 1.1 christos calling info_parse_xxx (). */ 40 1.1 christos char *info_parsed_nodename = (char *)NULL; 41 1.1 christos 42 1.1 christos /* Variable which holds the most recent line number parsed as a result of 43 1.1 christos calling info_parse_xxx (). */ 44 1.1 christos int info_parsed_line_number = 0; 45 1.1 christos 46 1.1 christos /* Functions to remember a filename or nodename for later return. */ 47 1.1 christos static void save_filename (char *filename); 48 1.1 christos static void saven_filename (char *filename, int len); 49 1.1 christos static void save_nodename (char *nodename); 50 1.1 christos static void saven_nodename (char *nodename, int len); 51 1.1 christos 52 1.1 christos /* How to get a reference (either menu or cross). */ 53 1.1 christos static REFERENCE **info_references_internal (char *label, 54 1.1 christos SEARCH_BINDING *binding); 55 1.1 christos 56 1.1 christos /* Parse the filename and nodename out of STRING. If STRING doesn't 57 1.1 christos contain a filename (i.e., it is NOT (FILENAME)NODENAME) then set 58 1.1 christos INFO_PARSED_FILENAME to NULL. If second argument NEWLINES_OKAY is 59 1.1 christos non-zero, it says to allow the nodename specification to cross a 60 1.1 christos newline boundary (i.e., only `,', `.', or `TAB' can end the spec). */ 61 1.1 christos void 62 1.1 christos info_parse_node (char *string, int newlines_okay) 63 1.1 christos { 64 1.1 christos register int i = 0; 65 1.1 christos 66 1.1 christos /* Default the answer. */ 67 1.1 christos save_filename ((char *)NULL); 68 1.1 christos save_nodename ((char *)NULL); 69 1.1 christos 70 1.1 christos /* Special case of nothing passed. Return nothing. */ 71 1.1 christos if (!string || !*string) 72 1.1 christos return; 73 1.1 christos 74 1.1 christos string += skip_whitespace (string); 75 1.1 christos 76 1.1 christos /* Check for (FILENAME)NODENAME. */ 77 1.1 christos if (*string == '(') 78 1.1 christos { 79 1.1 christos i = 0; 80 1.1 christos /* Advance past the opening paren. */ 81 1.1 christos string++; 82 1.1 christos 83 1.1 christos /* Find the closing paren. */ 84 1.1 christos while (string[i] && string[i] != ')') 85 1.1 christos i++; 86 1.1 christos 87 1.1 christos /* Remember parsed filename. */ 88 1.1 christos saven_filename (string, i); 89 1.1 christos 90 1.1 christos /* Point directly at the nodename. */ 91 1.1 christos string += i; 92 1.1 christos 93 1.1 christos if (*string) 94 1.1 christos string++; 95 1.1 christos } 96 1.1 christos 97 1.1 christos /* Parse out nodename. */ 98 1.1 christos i = skip_node_characters (string, newlines_okay); 99 1.1 christos saven_nodename (string, i); 100 1.1 christos canonicalize_whitespace (info_parsed_nodename); 101 1.1 christos if (info_parsed_nodename && !*info_parsed_nodename) 102 1.1 christos { 103 1.1 christos free (info_parsed_nodename); 104 1.1 christos info_parsed_nodename = (char *)NULL; 105 1.1 christos } 106 1.1 christos 107 1.1 christos /* Parse ``(line ...)'' part of menus, if any. */ 108 1.1 christos { 109 1.1 christos char *rest = string + i; 110 1.1 christos 111 1.1 christos /* Advance only if it's not already at end of string. */ 112 1.1 christos if (*rest) 113 1.1 christos rest++; 114 1.1 christos 115 1.1 christos /* Skip any whitespace first, and then a newline in case the item 116 1.1 christos was so long to contain the ``(line ...)'' string in the same 117 1.1 christos physical line. */ 118 1.1 christos while (whitespace(*rest)) 119 1.1 christos rest++; 120 1.1 christos if (*rest == '\n') 121 1.1 christos { 122 1.1 christos rest++; 123 1.1 christos while (whitespace(*rest)) 124 1.1 christos rest++; 125 1.1 christos } 126 1.1 christos 127 1.1 christos /* Are we looking at an opening parenthesis? That can only mean 128 1.1 christos we have a winner. :) */ 129 1.1 christos if (strncmp (rest, "(line ", strlen ("(line ")) == 0) 130 1.1 christos { 131 1.1 christos rest += strlen ("(line "); 132 1.1 christos info_parsed_line_number = strtol (rest, NULL, 0); 133 1.1 christos } 134 1.1 christos else 135 1.1 christos info_parsed_line_number = 0; 136 1.1 christos } 137 1.1 christos } 138 1.1 christos 139 1.1 christos /* Return the node addressed by LABEL in NODE (usually one of "Prev:", 140 1.1 christos "Next:", "Up:", "File:", or "Node:". After a call to this function, 141 1.1 christos the global INFO_PARSED_NODENAME and INFO_PARSED_FILENAME contain 142 1.1 christos the information. */ 143 1.1 christos void 144 1.1 christos info_parse_label (char *label, NODE *node) 145 1.1 christos { 146 1.1 christos register int i; 147 1.1 christos char *nodeline; 148 1.1 christos 149 1.1 christos /* Default answer to failure. */ 150 1.1 christos save_nodename ((char *)NULL); 151 1.1 christos save_filename ((char *)NULL); 152 1.1 christos 153 1.1 christos /* Find the label in the first line of this node. */ 154 1.1 christos nodeline = node->contents; 155 1.1 christos i = string_in_line (label, nodeline); 156 1.1 christos 157 1.1 christos if (i == -1) 158 1.1 christos return; 159 1.1 christos 160 1.1 christos nodeline += i; 161 1.1 christos nodeline += skip_whitespace (nodeline); 162 1.1 christos info_parse_node (nodeline, DONT_SKIP_NEWLINES); 163 1.1 christos } 164 1.1 christos 165 1.1 christos /* **************************************************************** */ 167 1.1 christos /* */ 168 1.1 christos /* Finding and Building Menus */ 169 1.1 christos /* */ 170 1.1 christos /* **************************************************************** */ 171 1.1 christos 172 1.1 christos /* Return a NULL terminated array of REFERENCE * which represents the menu 173 1.1 christos found in NODE. If there is no menu in NODE, just return a NULL pointer. */ 174 1.1 christos REFERENCE ** 175 1.1 christos info_menu_of_node (NODE *node) 176 1.1 christos { 177 1.1 christos long position; 178 1.1 christos SEARCH_BINDING tmp_search; 179 1.1 christos REFERENCE **menu = (REFERENCE **)NULL; 180 1.1 christos 181 1.1 christos tmp_search.buffer = node->contents; 182 1.1 christos tmp_search.start = 0; 183 1.1 christos tmp_search.end = node->nodelen; 184 1.1 christos tmp_search.flags = S_FoldCase; 185 1.1 christos 186 1.1 christos /* Find the start of the menu. */ 187 1.1 christos position = search_forward (INFO_MENU_LABEL, &tmp_search); 188 1.1 christos 189 1.1 christos if (position == -1) 190 1.1 christos return ((REFERENCE **) NULL); 191 1.1 christos 192 1.1 christos /* We have the start of the menu now. Glean menu items from the rest 193 1.1 christos of the node. */ 194 1.1 christos tmp_search.start = position + strlen (INFO_MENU_LABEL); 195 1.1 christos tmp_search.start += skip_line (tmp_search.buffer + tmp_search.start); 196 1.1 christos tmp_search.start--; 197 1.1 christos menu = info_menu_items (&tmp_search); 198 1.1 christos return (menu); 199 1.1 christos } 200 1.1 christos 201 1.1 christos /* Return a NULL terminated array of REFERENCE * which represents the cross 202 1.1 christos refrences found in NODE. If there are no cross references in NODE, just 203 1.1 christos return a NULL pointer. */ 204 1.1 christos REFERENCE ** 205 1.1 christos info_xrefs_of_node (NODE *node) 206 1.1 christos { 207 1.1 christos SEARCH_BINDING tmp_search; 208 1.1 christos 209 1.1 christos #if defined (HANDLE_MAN_PAGES) 210 1.1 christos if (node->flags & N_IsManPage) 211 1.1 christos return (xrefs_of_manpage (node)); 212 1.1 christos #endif 213 1.1 christos 214 1.1 christos tmp_search.buffer = node->contents; 215 1.1 christos tmp_search.start = 0; 216 1.1 christos tmp_search.end = node->nodelen; 217 1.1 christos tmp_search.flags = S_FoldCase; 218 1.1 christos 219 1.1 christos return (info_xrefs (&tmp_search)); 220 1.1 christos } 221 1.1 christos 222 1.1 christos /* Glean menu entries from BINDING->buffer + BINDING->start until we 223 1.1 christos have looked at the entire contents of BINDING. Return an array 224 1.1 christos of REFERENCE * that represents each menu item in this range. */ 225 1.1 christos REFERENCE ** 226 1.1 christos info_menu_items (SEARCH_BINDING *binding) 227 1.1 christos { 228 1.1 christos return (info_references_internal (INFO_MENU_ENTRY_LABEL, binding)); 229 1.1 christos } 230 1.1 christos 231 1.1 christos /* Glean cross references from BINDING->buffer + BINDING->start until 232 1.1 christos BINDING->end. Return an array of REFERENCE * that represents each 233 1.1 christos cross reference in this range. */ 234 1.1 christos REFERENCE ** 235 1.1 christos info_xrefs (SEARCH_BINDING *binding) 236 1.1 christos { 237 1.1 christos return (info_references_internal (INFO_XREF_LABEL, binding)); 238 1.1 christos } 239 1.1 christos 240 1.1 christos /* Glean cross references or menu items from BINDING. Return an array 241 1.1 christos of REFERENCE * that represents the items found. */ 242 1.1 christos static REFERENCE ** 243 1.1 christos info_references_internal (char *label, SEARCH_BINDING *binding) 244 1.1 christos { 245 1.1 christos SEARCH_BINDING tmp_search; 246 1.1 christos REFERENCE **refs = (REFERENCE **)NULL; 247 1.1 christos int refs_index = 0, refs_slots = 0; 248 1.1 christos int searching_for_menu_items = 0; 249 1.1 christos long position; 250 1.1 christos 251 1.1 christos tmp_search.buffer = binding->buffer; 252 1.1 christos tmp_search.start = binding->start; 253 1.1 christos tmp_search.end = binding->end; 254 1.1 christos tmp_search.flags = S_FoldCase | S_SkipDest; 255 1.1 christos 256 1.1 christos searching_for_menu_items = (strcasecmp (label, INFO_MENU_ENTRY_LABEL) == 0); 257 1.1 christos 258 1.1 christos while ((position = search_forward (label, &tmp_search)) != -1) 259 1.1 christos { 260 1.1 christos int offset, start; 261 1.1 christos char *refdef; 262 1.1 christos REFERENCE *entry; 263 1.1 christos 264 1.1 christos tmp_search.start = position; 265 1.1 christos tmp_search.start += skip_whitespace (tmp_search.buffer + tmp_search.start); 266 1.1 christos start = tmp_search.start - binding->start; 267 1.1 christos refdef = tmp_search.buffer + tmp_search.start; 268 1.1 christos offset = string_in_line (":", refdef); 269 1.1 christos 270 1.1 christos /* When searching for menu items, if no colon, there is no 271 1.1 christos menu item on this line. */ 272 1.1 christos if (offset == -1) 273 1.1 christos { 274 1.1 christos if (searching_for_menu_items) 275 1.1 christos continue; 276 1.1 christos else 277 1.1 christos { 278 1.1 christos int temp; 279 1.1 christos 280 1.1 christos temp = skip_line (refdef); 281 1.1 christos offset = string_in_line (":", refdef + temp); 282 1.1 christos if (offset == -1) 283 1.1 christos continue; /* Give up? */ 284 1.1 christos else 285 1.1 christos offset += temp; 286 1.1 christos } 287 1.1 christos } 288 1.1 christos 289 1.1 christos entry = (REFERENCE *)xmalloc (sizeof (REFERENCE)); 290 1.1 christos entry->filename = (char *)NULL; 291 1.1 christos entry->nodename = (char *)NULL; 292 1.1 christos entry->label = (char *)xmalloc (offset); 293 1.1 christos strncpy (entry->label, refdef, offset - 1); 294 1.1 christos entry->label[offset - 1] = '\0'; 295 1.1 christos canonicalize_whitespace (entry->label); 296 1.1 christos 297 1.1 christos refdef += offset; 298 1.1 christos entry->start = start; 299 1.1 christos entry->end = refdef - binding->buffer; 300 1.1 christos 301 1.1 christos /* If this reference entry continues with another ':' then the 302 1.1 christos nodename is the same as the label. */ 303 1.1 christos if (*refdef == ':') 304 1.1 christos { 305 1.1 christos entry->nodename = xstrdup (entry->label); 306 1.1 christos } 307 1.1 christos else 308 1.1 christos { 309 1.1 christos /* This entry continues with a specific nodename. Parse the 310 1.1 christos nodename from the specification. */ 311 1.1 christos 312 1.1 christos refdef += skip_whitespace_and_newlines (refdef); 313 1.1 christos 314 1.1 christos if (searching_for_menu_items) 315 1.1 christos info_parse_node (refdef, DONT_SKIP_NEWLINES); 316 1.1 christos else 317 1.1 christos info_parse_node (refdef, SKIP_NEWLINES); 318 1.1 christos 319 1.1 christos if (info_parsed_filename) 320 1.1 christos entry->filename = xstrdup (info_parsed_filename); 321 1.1 christos 322 1.1 christos if (info_parsed_nodename) 323 1.1 christos entry->nodename = xstrdup (info_parsed_nodename); 324 1.1 christos 325 1.1 christos entry->line_number = info_parsed_line_number; 326 1.1 christos } 327 1.1 christos 328 1.1 christos add_pointer_to_array 329 1.1 christos (entry, refs_index, refs, refs_slots, 50, REFERENCE *); 330 1.1 christos } 331 1.1 christos return (refs); 332 1.1 christos } 333 1.1 christos 334 1.1 christos /* Get the entry associated with LABEL in REFERENCES. Return a pointer 335 1.1 christos to the ENTRY if found, or NULL. */ 336 1.1 christos REFERENCE * 337 1.1 christos info_get_labeled_reference (char *label, REFERENCE **references) 338 1.1 christos { 339 1.1 christos register int i; 340 1.1 christos REFERENCE *entry; 341 1.1 christos 342 1.1 christos for (i = 0; references && (entry = references[i]); i++) 343 1.1 christos { 344 1.1 christos if (strcmp (label, entry->label) == 0) 345 1.1 christos return (entry); 346 1.1 christos } 347 1.1 christos return ((REFERENCE *)NULL); 348 1.1 christos } 349 1.1 christos 350 1.1 christos /* A utility function for concatenating REFERENCE **. Returns a new 351 1.1 christos REFERENCE ** which is the concatenation of REF1 and REF2. The REF1 352 1.1 christos and REF2 arrays are freed, but their contents are not. */ 353 1.1 christos REFERENCE ** 354 1.1 christos info_concatenate_references (REFERENCE **ref1, REFERENCE **ref2) 355 1.1 christos { 356 1.1 christos register int i, j; 357 1.1 christos REFERENCE **result; 358 1.1 christos int size; 359 1.1 christos 360 1.1 christos /* With one argument passed as NULL, simply return the other arg. */ 361 1.1 christos if (!ref1) 362 1.1 christos return (ref2); 363 1.1 christos else if (!ref2) 364 1.1 christos return (ref1); 365 1.1 christos 366 1.1 christos /* Get the total size of the slots that we will need. */ 367 1.1 christos for (i = 0; ref1[i]; i++); 368 1.1 christos size = i; 369 1.1 christos for (i = 0; ref2[i]; i++); 370 1.1 christos size += i; 371 1.1 christos 372 1.1 christos result = (REFERENCE **)xmalloc ((1 + size) * sizeof (REFERENCE *)); 373 1.1 christos 374 1.1 christos /* Copy the contents over. */ 375 1.1 christos for (i = 0; ref1[i]; i++) 376 1.1 christos result[i] = ref1[i]; 377 1.1 christos 378 1.1 christos j = i; 379 1.1 christos for (i = 0; ref2[i]; i++) 380 1.1 christos result[j++] = ref2[i]; 381 1.1 christos 382 1.1 christos result[j] = (REFERENCE *)NULL; 383 1.1 christos free (ref1); 384 1.1 christos free (ref2); 385 1.1 christos return (result); 386 1.1 christos } 387 1.1 christos 388 1.1 christos 389 1.1 christos 390 1.1 christos /* Copy a reference structure. Since we tend to free everything at 392 1.1 christos every opportunity, we don't share any points, but copy everything into 393 1.1 christos new memory. */ 394 1.1 christos REFERENCE * 395 1.1 christos info_copy_reference (REFERENCE *src) 396 1.1 christos { 397 1.1 christos REFERENCE *dest = xmalloc (sizeof (REFERENCE)); 398 1.1 christos dest->label = src->label ? xstrdup (src->label) : NULL; 399 1.1 christos dest->filename = src->filename ? xstrdup (src->filename) : NULL; 400 1.1 christos dest->nodename = src->nodename ? xstrdup (src->nodename) : NULL; 401 1.1 christos dest->start = src->start; 402 1.1 christos dest->end = src->end; 403 1.1 christos 404 1.1 christos return dest; 405 1.1 christos } 406 1.1 christos 407 1.1 christos 408 1.1 christos 409 1.1 christos /* Free the data associated with REFERENCES. */ 411 1.1 christos void 412 1.1 christos info_free_references (REFERENCE **references) 413 1.1 christos { 414 1.1 christos register int i; 415 1.1 christos REFERENCE *entry; 416 1.1 christos 417 1.1 christos if (references) 418 1.1 christos { 419 1.1 christos for (i = 0; references && (entry = references[i]); i++) 420 1.1 christos { 421 1.1 christos maybe_free (entry->label); 422 1.1 christos maybe_free (entry->filename); 423 1.1 christos maybe_free (entry->nodename); 424 1.1 christos 425 1.1 christos free (entry); 426 1.1 christos } 427 1.1 christos 428 1.1 christos free (references); 429 1.1 christos } 430 1.1 christos } 431 1.1 christos 432 1.1 christos /* Search for sequences of whitespace or newlines in STRING, replacing 433 1.1 christos all such sequences with just a single space. Remove whitespace from 434 1.1 christos start and end of string. */ 435 1.1 christos void 436 1.1 christos canonicalize_whitespace (char *string) 437 1.1 christos { 438 1.1 christos register int i, j; 439 1.1 christos int len, whitespace_found, whitespace_loc = 0; 440 1.1 christos char *temp; 441 1.1 christos 442 1.1 christos if (!string) 443 1.1 christos return; 444 1.1 christos 445 1.1 christos len = strlen (string); 446 1.1 christos temp = (char *)xmalloc (1 + len); 447 1.1 christos 448 1.1 christos /* Search for sequences of whitespace or newlines. Replace all such 449 1.1 christos sequences in the string with just a single space. */ 450 1.1 christos 451 1.1 christos whitespace_found = 0; 452 1.1 christos for (i = 0, j = 0; string[i]; i++) 453 1.1 christos { 454 1.1 christos if (whitespace_or_newline (string[i])) 455 1.1 christos { 456 1.1 christos whitespace_found++; 457 1.1 christos whitespace_loc = i; 458 1.1 christos continue; 459 1.1 christos } 460 1.1 christos else 461 1.1 christos { 462 1.1 christos if (whitespace_found && whitespace_loc) 463 1.1 christos { 464 1.1 christos whitespace_found = 0; 465 1.1 christos 466 1.1 christos /* Suppress whitespace at start of string. */ 467 1.1 christos if (j) 468 1.1 christos temp[j++] = ' '; 469 1.1 christos } 470 1.1 christos 471 1.1 christos temp[j++] = string[i]; 472 1.1 christos } 473 1.1 christos } 474 1.1 christos 475 1.1 christos /* Kill trailing whitespace. */ 476 1.1 christos if (j && whitespace (temp[j - 1])) 477 1.1 christos j--; 478 1.1 christos 479 1.1 christos temp[j] = '\0'; 480 1.1 christos strcpy (string, temp); 481 1.1 christos free (temp); 482 1.1 christos } 483 1.1 christos 484 1.1 christos /* String representation of a char returned by printed_representation (). */ 485 1.1 christos static char the_rep[10]; 486 1.1 christos 487 1.1 christos /* Return a pointer to a string which is the printed representation 488 1.1 christos of CHARACTER if it were printed at HPOS. */ 489 1.1 christos char * 490 1.1 christos printed_representation (unsigned char character, int hpos) 491 1.1 christos { 492 1.1 christos register int i = 0; 493 1.1 christos int printable_limit = ISO_Latin_p ? 255 : 127; 494 1.1 christos 495 1.1 christos if (raw_escapes_p && character == '\033') 496 1.1 christos the_rep[i++] = character; 497 1.1 christos /* Show CTRL-x as ^X. */ 498 1.1 christos else if (iscntrl (character) && character < 127) 499 1.1 christos { 500 1.1 christos switch (character) 501 1.1 christos { 502 1.1 christos case '\r': 503 1.1 christos case '\n': 504 1.1 christos the_rep[i++] = character; 505 1.1 christos break; 506 1.1 christos 507 1.1 christos case '\t': 508 1.1 christos { 509 1.1 christos int tw; 510 1.1 christos 511 1.1 christos tw = ((hpos + 8) & 0xf8) - hpos; 512 1.1 christos while (i < tw) 513 1.1 christos the_rep[i++] = ' '; 514 1.1 christos } 515 1.1 christos break; 516 1.1 christos 517 1.1 christos default: 518 1.1 christos the_rep[i++] = '^'; 519 1.1 christos the_rep[i++] = (character | 0x40); 520 1.1 christos } 521 1.1 christos } 522 1.1 christos /* Show META-x as 0370. */ 523 1.1 christos else if (character > printable_limit) 524 1.1 christos { 525 1.1 christos sprintf (the_rep + i, "\\%0o", character); 526 1.1 christos i = strlen (the_rep); 527 1.1 christos } 528 1.1 christos else if (character == DEL) 529 1.1 christos { 530 1.1 christos the_rep[i++] = '^'; 531 1.1 christos the_rep[i++] = '?'; 532 1.1 christos } 533 1.1 christos else 534 1.1 christos the_rep[i++] = character; 535 1.1 christos 536 1.1 christos the_rep[i] = 0; 537 1.1 christos 538 1.1 christos return the_rep; 539 1.1 christos } 540 1.1 christos 541 1.1 christos 542 1.1 christos /* **************************************************************** */ 544 1.1 christos /* */ 545 1.1 christos /* Functions Static To This File */ 546 1.1 christos /* */ 547 1.1 christos /* **************************************************************** */ 548 1.1 christos 549 1.1 christos /* Amount of space allocated to INFO_PARSED_FILENAME via xmalloc (). */ 550 1.1 christos static int parsed_filename_size = 0; 551 1.1 christos 552 1.1 christos /* Amount of space allocated to INFO_PARSED_NODENAME via xmalloc (). */ 553 1.1 christos static int parsed_nodename_size = 0; 554 1.1 christos 555 1.1 christos static void save_string (char *string, char **string_p, int *string_size_p); 556 1.1 christos static void saven_string (char *string, int len, char **string_p, 557 1.1 christos int *string_size_p); 558 1.1 christos 559 1.1 christos /* Remember FILENAME in PARSED_FILENAME. An empty FILENAME is translated 560 1.1 christos to a NULL pointer in PARSED_FILENAME. */ 561 1.1 christos static void 562 1.1 christos save_filename (char *filename) 563 1.1 christos { 564 1.1 christos save_string (filename, &info_parsed_filename, &parsed_filename_size); 565 1.1 christos } 566 1.1 christos 567 1.1 christos /* Just like save_filename (), but you pass the length of the string. */ 568 1.1 christos static void 569 1.1 christos saven_filename (char *filename, int len) 570 1.1 christos { 571 1.1 christos saven_string (filename, len, 572 1.1 christos &info_parsed_filename, &parsed_filename_size); 573 1.1 christos } 574 1.1 christos 575 1.1 christos /* Remember NODENAME in PARSED_NODENAME. An empty NODENAME is translated 576 1.1 christos to a NULL pointer in PARSED_NODENAME. */ 577 1.1 christos static void 578 1.1 christos save_nodename (char *nodename) 579 1.1 christos { 580 1.1 christos save_string (nodename, &info_parsed_nodename, &parsed_nodename_size); 581 1.1 christos } 582 1.1 christos 583 1.1 christos /* Just like save_nodename (), but you pass the length of the string. */ 584 1.1 christos static void 585 1.1 christos saven_nodename (char *nodename, int len) 586 1.1 christos { 587 1.1 christos saven_string (nodename, len, 588 1.1 christos &info_parsed_nodename, &parsed_nodename_size); 589 1.1 christos } 590 1.1 christos 591 1.1 christos /* Remember STRING in STRING_P. STRING_P should currently have STRING_SIZE_P 592 1.1 christos bytes allocated to it. An empty STRING is translated to a NULL pointer 593 1.1 christos in STRING_P. */ 594 1.1 christos static void 595 1.1 christos save_string (char *string, char **string_p, int *string_size_p) 596 1.1 christos { 597 1.1 christos if (!string || !*string) 598 1.1 christos { 599 1.1 christos if (*string_p) 600 1.1 christos free (*string_p); 601 1.1 christos 602 1.1 christos *string_p = (char *)NULL; 603 1.1 christos *string_size_p = 0; 604 1.1 christos } 605 1.1 christos else 606 1.1 christos { 607 1.1 christos if (strlen (string) >= (unsigned int) *string_size_p) 608 1.1 christos *string_p = (char *)xrealloc 609 1.1 christos (*string_p, (*string_size_p = 1 + strlen (string))); 610 1.1 christos 611 1.1 christos strcpy (*string_p, string); 612 1.1 christos } 613 1.1 christos } 614 1.1 christos 615 1.1 christos /* Just like save_string (), but you also pass the length of STRING. */ 616 1.1 christos static void 617 1.1 christos saven_string (char *string, int len, char **string_p, int *string_size_p) 618 1.1 christos { 619 1.1 christos if (!string) 620 1.1 christos { 621 1.1 christos if (*string_p) 622 1.1 christos free (*string_p); 623 1.1 christos 624 1.1 christos *string_p = (char *)NULL; 625 1.1 christos *string_size_p = 0; 626 1.1 christos } 627 1.1 christos else 628 1.1 christos { 629 1.1 christos if (len >= *string_size_p) 630 1.1 christos *string_p = (char *)xrealloc (*string_p, (*string_size_p = 1 + len)); 631 1.1 christos 632 1.1 christos strncpy (*string_p, string, len); 633 1.1 christos (*string_p)[len] = '\0'; 634 1.1 christos } 635 1.1 christos } 636 1.1 christos 637 1.1 christos /* Return a pointer to the part of PATHNAME that simply defines the file. */ 638 1.1 christos char * 639 1.1 christos filename_non_directory (char *pathname) 640 1.1 christos { 641 1.1 christos register char *filename = pathname + strlen (pathname); 642 1.1 christos 643 1.1 christos if (HAVE_DRIVE (pathname)) 644 1.1 christos pathname += 2; 645 1.1 christos 646 1.1 christos while (filename > pathname && !IS_SLASH (filename[-1])) 647 1.1 christos filename--; 648 1.1 christos 649 1.1 christos return (filename); 650 1.1 christos } 651 1.1 christos 652 1.1 christos /* Return non-zero if NODE is one especially created by Info. */ 653 1.1 christos int 654 1.1 christos internal_info_node_p (NODE *node) 655 1.1 christos { 656 1.1 christos #if defined (NEVER) 657 1.1 christos if (node && 658 1.1 christos (node->filename && !*node->filename) && 659 1.1 christos !node->parent && node->nodename) 660 1.1 christos return (1); 661 1.1 christos else 662 1.1 christos return (0); 663 1.1 christos #else 664 1.1 christos return ((node != (NODE *)NULL) && ((node->flags & N_IsInternal) != 0)); 665 1.1 christos #endif /* !NEVER */ 666 1.1 christos } 667 1.1 christos 668 1.1 christos /* Make NODE appear to be one especially created by Info. */ 669 1.1 christos void 670 1.1 christos name_internal_node (NODE *node, char *name) 671 1.1 christos { 672 1.1 christos if (!node) 673 1.1 christos return; 674 1.1 christos 675 1.1 christos node->filename = ""; 676 1.1 christos node->parent = (char *)NULL; 677 1.1 christos node->nodename = name; 678 1.1 christos node->flags |= N_IsInternal; 679 1.1 christos } 680 1.1 christos 681 1.1 christos /* Return the window displaying NAME, the name of an internally created 682 1.1 christos Info window. */ 683 1.1 christos WINDOW * 684 1.1 christos get_internal_info_window (char *name) 685 1.1 christos { 686 1.1 christos WINDOW *win; 687 1.1 christos 688 1.1 christos for (win = windows; win; win = win->next) 689 1.1 christos if (internal_info_node_p (win->node) && 690 1.1 christos (strcmp (win->node->nodename, name) == 0)) 691 1.1 christos break; 692 1.1 christos 693 1.1 christos return (win); 694 1.1 christos } 695 1.1 christos 696 1.1 christos /* Return a window displaying the node NODE. */ 697 1.1 christos WINDOW * 698 1.1 christos get_window_of_node (NODE *node) 699 1.1 christos { 700 1.1 christos WINDOW *win = (WINDOW *)NULL; 701 1.1 christos 702 1.1 christos for (win = windows; win; win = win->next) 703 1.1 christos if (win->node == node) 704 break; 705 706 return (win); 707 } 708