1
1
/* info-utils.c -- miscellanous.
2
$Id: info-utils.c,v 1.7 1998/08/10 18:07:47 karl Exp $
2
$Id: info-utils.c,v 1.4 2004/04/11 17:56:45 karl Exp $
4
Copyright (C) 1993, 98 Free Software Foundation, Inc.
4
Copyright (C) 1993, 1998, 2003, 2004 Free Software Foundation, Inc.
6
6
This program is free software; you can redistribute it and/or modify
7
7
it under the terms of the GNU General Public License as published by
17
17
along with this program; if not, write to the Free Software
18
18
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20
Written by Brian Fox (bfox@ai.mit.edu). */
20
Originally written by Brian Fox (bfox@ai.mit.edu). */
23
23
#include "info-utils.h"
37
37
calling info_parse_xxx (). */
38
38
char *info_parsed_nodename = (char *)NULL;
40
/* Variable which holds the most recent line number parsed as a result of
41
calling info_parse_xxx (). */
42
int info_parsed_line_number = 0;
40
44
/* Functions to remember a filename or nodename for later return. */
41
static void save_filename (), saven_filename ();
42
static void save_nodename (), saven_nodename ();
45
static void save_filename (char *filename);
46
static void saven_filename (char *filename, int len);
47
static void save_nodename (char *nodename);
48
static void saven_nodename (char *nodename, int len);
44
50
/* How to get a reference (either menu or cross). */
45
static REFERENCE **info_references_internal ();
51
static REFERENCE **info_references_internal (char *label,
52
SEARCH_BINDING *binding);
47
54
/* Parse the filename and nodename out of STRING. If STRING doesn't
48
55
contain a filename (i.e., it is NOT (FILENAME)NODENAME) then set
50
57
non-zero, it says to allow the nodename specification to cross a
51
58
newline boundary (i.e., only `,', `.', or `TAB' can end the spec). */
53
info_parse_node (string, newlines_okay)
60
info_parse_node (char *string, int newlines_okay)
57
62
register int i = 0;
96
101
free (info_parsed_nodename);
97
102
info_parsed_nodename = (char *)NULL;
105
/* Parse ``(line ...)'' part of menus, if any. */
107
char *rest = string + i;
109
/* Advance only if it's not already at end of string. */
113
/* Skip any whitespace first, and then a newline in case the item
114
was so long to contain the ``(line ...)'' string in the same
116
while (whitespace(*rest))
121
while (whitespace(*rest))
125
/* Are we looking at an opening parenthesis? That can only mean
126
we have a winner. :) */
127
if (strncmp (rest, "(line ", strlen ("(line ")) == 0)
129
rest += strlen ("(line ");
130
info_parsed_line_number = strtol (rest, NULL, 0);
133
info_parsed_line_number = 0;
101
137
/* Return the node addressed by LABEL in NODE (usually one of "Prev:",
135
169
/* Return a NULL terminated array of REFERENCE * which represents the menu
136
170
found in NODE. If there is no menu in NODE, just return a NULL pointer. */
138
info_menu_of_node (node)
172
info_menu_of_node (NODE *node)
142
SEARCH_BINDING search;
175
SEARCH_BINDING tmp_search;
143
176
REFERENCE **menu = (REFERENCE **)NULL;
145
search.buffer = node->contents;
147
search.end = node->nodelen;
148
search.flags = S_FoldCase;
178
tmp_search.buffer = node->contents;
179
tmp_search.start = 0;
180
tmp_search.end = node->nodelen;
181
tmp_search.flags = S_FoldCase;
150
183
/* Find the start of the menu. */
151
position = search_forward (INFO_MENU_LABEL, &search);
184
position = search_forward (INFO_MENU_LABEL, &tmp_search);
153
186
if (position == -1)
154
187
return ((REFERENCE **) NULL);
156
189
/* We have the start of the menu now. Glean menu items from the rest
158
search.start = position + strlen (INFO_MENU_LABEL);
159
search.start += skip_line (search.buffer + search.start);
161
menu = info_menu_items (&search);
191
tmp_search.start = position + strlen (INFO_MENU_LABEL);
192
tmp_search.start += skip_line (tmp_search.buffer + tmp_search.start);
194
menu = info_menu_items (&tmp_search);
166
199
refrences found in NODE. If there are no cross references in NODE, just
167
200
return a NULL pointer. */
169
info_xrefs_of_node (node)
202
info_xrefs_of_node (NODE *node)
172
SEARCH_BINDING search;
204
SEARCH_BINDING tmp_search;
174
206
#if defined (HANDLE_MAN_PAGES)
175
207
if (node->flags & N_IsManPage)
176
208
return (xrefs_of_manpage (node));
179
search.buffer = node->contents;
181
search.end = node->nodelen;
182
search.flags = S_FoldCase;
211
tmp_search.buffer = node->contents;
212
tmp_search.start = 0;
213
tmp_search.end = node->nodelen;
214
tmp_search.flags = S_FoldCase;
184
return (info_xrefs (&search));
216
return (info_xrefs (&tmp_search));
187
219
/* Glean menu entries from BINDING->buffer + BINDING->start until we
188
220
have looked at the entire contents of BINDING. Return an array
189
221
of REFERENCE * that represents each menu item in this range. */
191
info_menu_items (binding)
192
SEARCH_BINDING *binding;
223
info_menu_items (SEARCH_BINDING *binding)
194
225
return (info_references_internal (INFO_MENU_ENTRY_LABEL, binding));
198
229
BINDING->end. Return an array of REFERENCE * that represents each
199
230
cross reference in this range. */
202
SEARCH_BINDING *binding;
232
info_xrefs (SEARCH_BINDING *binding)
204
234
return (info_references_internal (INFO_XREF_LABEL, binding));
207
237
/* Glean cross references or menu items from BINDING. Return an array
208
238
of REFERENCE * that represents the items found. */
209
239
static REFERENCE **
210
info_references_internal (label, binding)
212
SEARCH_BINDING *binding;
240
info_references_internal (char *label, SEARCH_BINDING *binding)
214
SEARCH_BINDING search;
242
SEARCH_BINDING tmp_search;
215
243
REFERENCE **refs = (REFERENCE **)NULL;
216
244
int refs_index = 0, refs_slots = 0;
217
245
int searching_for_menu_items = 0;
220
search.buffer = binding->buffer;
221
search.start = binding->start;
222
search.end = binding->end;
223
search.flags = S_FoldCase | S_SkipDest;
248
tmp_search.buffer = binding->buffer;
249
tmp_search.start = binding->start;
250
tmp_search.end = binding->end;
251
tmp_search.flags = S_FoldCase | S_SkipDest;
225
253
searching_for_menu_items = (strcasecmp (label, INFO_MENU_ENTRY_LABEL) == 0);
227
while ((position = search_forward (label, &search)) != -1)
255
while ((position = search_forward (label, &tmp_search)) != -1)
229
257
int offset, start;
231
259
REFERENCE *entry;
233
search.start = position;
234
search.start += skip_whitespace (search.buffer + search.start);
235
start = search.start - binding->start;
236
refdef = search.buffer + search.start;
261
tmp_search.start = position;
262
tmp_search.start += skip_whitespace (tmp_search.buffer + tmp_search.start);
263
start = tmp_search.start - binding->start;
264
refdef = tmp_search.buffer + tmp_search.start;
237
265
offset = string_in_line (":", refdef);
239
267
/* When searching for menu items, if no colon, there is no
301
331
/* Get the entry associated with LABEL in REFERENCES. Return a pointer
302
332
to the ENTRY if found, or NULL. */
304
info_get_labeled_reference (label, references)
306
REFERENCE **references;
334
info_get_labeled_reference (char *label, REFERENCE **references)
309
337
REFERENCE *entry;
320
348
REFERENCE ** which is the concatenation of REF1 and REF2. The REF1
321
349
and REF2 arrays are freed, but their contents are not. */
323
info_concatenate_references (ref1, ref2)
324
REFERENCE **ref1, **ref2;
351
info_concatenate_references (REFERENCE **ref1, REFERENCE **ref2)
326
353
register int i, j;
327
354
REFERENCE **result;
387
/* Copy a reference structure. Since we tend to free everything at
388
every opportunity, we don't share any points, but copy everything into
391
info_copy_reference (REFERENCE *src)
393
REFERENCE *dest = xmalloc (sizeof (REFERENCE));
394
dest->label = src->label ? xstrdup (src->label) : NULL;
395
dest->filename = src->filename ? xstrdup (src->filename) : NULL;
396
dest->nodename = src->nodename ? xstrdup (src->nodename) : NULL;
397
dest->start = src->start;
398
dest->end = src->end;
358
405
/* Free the data associated with REFERENCES. */
360
info_free_references (references)
361
REFERENCE **references;
407
info_free_references (REFERENCE **references)
364
410
REFERENCE *entry;
382
428
all such sequences with just a single space. Remove whitespace from
383
429
start and end of string. */
385
canonicalize_whitespace (string)
431
canonicalize_whitespace (char *string)
388
433
register int i, j;
389
int len, whitespace_found, whitespace_loc;
434
int len, whitespace_found, whitespace_loc = 0;
437
482
/* Return a pointer to a string which is the printed representation
438
483
of CHARACTER if it were printed at HPOS. */
440
printed_representation (character, hpos)
441
unsigned char character;
485
printed_representation (unsigned char character, int hpos)
444
487
register int i = 0;
445
488
int printable_limit = ISO_Latin_p ? 255 : 127;
490
if (raw_escapes_p && character == '\033')
491
the_rep[i++] = character;
447
492
/* Show CTRL-x as ^X. */
448
if (iscntrl (character) && character < 127)
493
else if (iscntrl (character) && character < 127)
450
495
switch (character)
501
546
/* Amount of space allocated to INFO_PARSED_NODENAME via xmalloc (). */
502
547
static int parsed_nodename_size = 0;
504
static void save_string (), saven_string ();
549
static void save_string (char *string, char **string_p, int *string_size_p);
550
static void saven_string (char *string, int len, char **string_p,
506
553
/* Remember FILENAME in PARSED_FILENAME. An empty FILENAME is translated
507
554
to a NULL pointer in PARSED_FILENAME. */
509
save_filename (filename)
556
save_filename (char *filename)
512
558
save_string (filename, &info_parsed_filename, &parsed_filename_size);
515
561
/* Just like save_filename (), but you pass the length of the string. */
517
saven_filename (filename, len)
563
saven_filename (char *filename, int len)
521
565
saven_string (filename, len,
522
566
&info_parsed_filename, &parsed_filename_size);
525
569
/* Remember NODENAME in PARSED_NODENAME. An empty NODENAME is translated
526
570
to a NULL pointer in PARSED_NODENAME. */
528
save_nodename (nodename)
572
save_nodename (char *nodename)
531
574
save_string (nodename, &info_parsed_nodename, &parsed_nodename_size);
534
577
/* Just like save_nodename (), but you pass the length of the string. */
536
saven_nodename (nodename, len)
579
saven_nodename (char *nodename, int len)
540
581
saven_string (nodename, len,
541
582
&info_parsed_nodename, &parsed_nodename_size);
545
586
bytes allocated to it. An empty STRING is translated to a NULL pointer
548
save_string (string, string_p, string_size_p)
589
save_string (char *string, char **string_p, int *string_size_p)
553
591
if (!string || !*string)
563
if (strlen (string) >= *string_size_p)
601
if (strlen (string) >= (unsigned int) *string_size_p)
564
602
*string_p = (char *)xrealloc
565
603
(*string_p, (*string_size_p = 1 + strlen (string)));
571
609
/* Just like save_string (), but you also pass the length of STRING. */
573
saven_string (string, len, string_p, string_size_p)
611
saven_string (char *string, int len, char **string_p, int *string_size_p)
597
631
/* Return a pointer to the part of PATHNAME that simply defines the file. */
599
filename_non_directory (pathname)
633
filename_non_directory (char *pathname)
602
635
register char *filename = pathname + strlen (pathname);