📄 nodes.c
字号:
}/* Grovel FILE_BUFFER->contents finding tags and nodes, and filling in the various slots. This can also be used to rebuild a tag or node table. */voidbuild_tags_and_nodes (file_buffer) FILE_BUFFER *file_buffer;{ SEARCH_BINDING binding; long position; free_file_buffer_tags (file_buffer); file_buffer->flags &= ~N_HasTagsTable; /* See if there is a tags table in this info file. */ binding.buffer = file_buffer->contents; binding.start = file_buffer->filesize; binding.end = binding.start - 1000; if (binding.end < 0) binding.end = 0; binding.flags = S_FoldCase; position = search_backward (TAGS_TABLE_END_LABEL, &binding); /* If there is a tag table, find the start of it, and grovel over it extracting tag information. */ if (position != -1) while (1) { long tags_table_begin, tags_table_end; binding.end = position; binding.start = binding.end - 5 - strlen (TAGS_TABLE_END_LABEL); if (binding.start < 0) binding.start = 0; position = find_node_separator (&binding); /* For this test, (and all others here) failure indicates a bogus tags table. Grovel the file. */ if (position == -1) break; /* Remember the end of the tags table. */ binding.start = position; tags_table_end = binding.start; binding.end = 0; /* Locate the start of the tags table. */ position = search_backward (TAGS_TABLE_BEG_LABEL, &binding); if (position == -1) break; binding.end = position; binding.start = binding.end - 5 - strlen (TAGS_TABLE_BEG_LABEL); position = find_node_separator (&binding); if (position == -1) break; /* The file contains a valid tags table. Fill the FILE_BUFFER's tags member. */ file_buffer->flags |= N_HasTagsTable; tags_table_begin = position; /* If this isn't an indirect tags table, just remember the nodes described locally in this tags table. Note that binding.end is pointing to just after the beginning label. */ binding.start = binding.end; binding.end = file_buffer->filesize; if (!looking_at (TAGS_TABLE_IS_INDIRECT_LABEL, &binding)) { binding.start = tags_table_begin; binding.end = tags_table_end; get_nodes_of_tags_table (file_buffer, &binding); return; } else { /* This is an indirect tags table. Build TAGS member. */ SEARCH_BINDING indirect; indirect.start = tags_table_begin; indirect.end = 0; indirect.buffer = binding.buffer; indirect.flags = S_FoldCase; position = search_backward (INDIRECT_TAGS_TABLE_LABEL, &indirect); if (position == -1) { /* This file is malformed. Give up. */ return; } indirect.start = position; indirect.end = tags_table_begin; binding.start = tags_table_begin; binding.end = tags_table_end; get_tags_of_indirect_tags_table (file_buffer, &indirect, &binding); return; } } /* This file doesn't contain any kind of tags table. Grovel the file and build node entries for it. */ get_nodes_of_info_file (file_buffer);}/* Search through FILE_BUFFER->contents building an array of TAG *, one entry per each node present in the file. Store the tags in FILE_BUFFER->tags, and the number of allocated slots in FILE_BUFFER->tags_slots. */static voidget_nodes_of_info_file (file_buffer) FILE_BUFFER *file_buffer;{ long nodestart; int tags_index = 0; SEARCH_BINDING binding; binding.buffer = file_buffer->contents; binding.start = 0; binding.end = file_buffer->filesize; binding.flags = S_FoldCase; while ((nodestart = find_node_separator (&binding)) != -1) { int start, end; char *nodeline; TAG *entry; /* Skip past the characters just found. */ binding.start = nodestart; binding.start += skip_node_separator (binding.buffer + binding.start); /* Move to the start of the line defining the node. */ nodeline = binding.buffer + binding.start; /* Find "Node:" */ start = string_in_line (INFO_NODE_LABEL, nodeline); /* If not there, this is not the start of a node. */ if (start == -1) continue; /* Find the start of the nodename. */ start += skip_whitespace (nodeline + start); /* Find the end of the nodename. */ end = start + skip_node_characters (nodeline + start, DONT_SKIP_NEWLINES); /* Okay, we have isolated the node name, and we know where the node starts. Remember this information in a NODE structure. */ entry = (TAG *)xmalloc (sizeof (TAG)); entry->nodename = (char *)xmalloc (1 + (end - start)); strncpy (entry->nodename, nodeline + start, end - start); entry->nodename[end - start] = '\0'; entry->nodestart = nodestart; { SEARCH_BINDING node_body; node_body.buffer = binding.buffer + binding.start; node_body.start = 0; node_body.end = binding.end - binding.start; node_body.flags = S_FoldCase; entry->nodelen = get_node_length (&node_body); } entry->filename = file_buffer->fullpath; /* Add this tag to the array of tag structures in this FILE_BUFFER. */ add_pointer_to_array (entry, tags_index, file_buffer->tags, file_buffer->tags_slots, 100, TAG *); }}/* Return the length of the node which starts at BINDING. */static longget_node_length (binding) SEARCH_BINDING *binding;{ register int i; char *body; /* From the Info-RFC file: [A node] ends with either a ^_, a ^L, or the end of file. */ for (i = binding->start, body = binding->buffer; i < binding->end; i++) { if (body[i] == INFO_FF || body[i] == INFO_COOKIE) break; } return ((long) i - binding->start);}/* Build and save the array of nodes in FILE_BUFFER by searching through the contents of BUFFER_BINDING for a tags table, and groveling the contents. */static voidget_nodes_of_tags_table (file_buffer, buffer_binding) FILE_BUFFER *file_buffer; SEARCH_BINDING *buffer_binding;{ int offset, tags_index = 0; SEARCH_BINDING *search; long position; search = copy_binding (buffer_binding); /* Find the start of the tags table. */ position = find_tags_table (search); /* If none, we're all done. */ if (position == -1) return; /* Move to one character before the start of the actual table. */ search->start = position; search->start += skip_node_separator (search->buffer + search->start); search->start += strlen (TAGS_TABLE_BEG_LABEL); search->start--; /* The tag table consists of lines containing node names and positions. Do each line until we find one that doesn't contain a node name. */ while ((position = search_forward ("\n", search)) != -1) { TAG *entry; char *nodedef; /* Prepare to skip this line. */ search->start = position; search->start++; /* Skip past informative "(Indirect)" tags table line. */ if (!tags_index && looking_at (TAGS_TABLE_IS_INDIRECT_LABEL, search)) continue; /* Find the label preceding the node name. */ offset = string_in_line (INFO_NODE_LABEL, search->buffer + search->start); /* If not there, not a defining line, so we must be out of the tags table. */ if (offset == -1) break; /* Point to the beginning of the node definition. */ search->start += offset; nodedef = search->buffer + search->start; nodedef += skip_whitespace (nodedef); /* Move past the node's name. */ for (offset = 0; (nodedef[offset]) && (nodedef[offset] != INFO_TAGSEP); offset++); if (nodedef[offset] != INFO_TAGSEP) continue; entry = (TAG *)xmalloc (sizeof (TAG)); entry->nodename = (char *)xmalloc (1 + offset); strncpy (entry->nodename, nodedef, offset); entry->nodename[offset] = '\0'; offset++; entry->nodestart = (long) atol (nodedef + offset); /* We don't know the length of this node yet. */ entry->nodelen = -1; /* The filename of this node is currently known as the same as the name of this file. */ entry->filename = file_buffer->fullpath; /* Add this node structure to the array of node structures in this FILE_BUFFER. */ add_pointer_to_array (entry, tags_index, file_buffer->tags, file_buffer->tags_slots, 100, TAG *); } free (search);}/* A structure used only in get_tags_of_indirect_tags_table () to hold onto an intermediate value. */typedef struct { char *filename; long first_byte;} SUBFILE;/* Remember in FILE_BUFFER the nodenames, subfilenames, and offsets within the subfiles of every node which appears in TAGS_BINDING. The 2nd argument is a binding surrounding the indirect files list. */static voidget_tags_of_indirect_tags_table (file_buffer, indirect_binding, tags_binding) FILE_BUFFER *file_buffer; SEARCH_BINDING *indirect_binding, *tags_binding;{ register int i; SUBFILE **subfiles = (SUBFILE **)NULL; int subfiles_index = 0, subfiles_slots = 0; TAG *entry; /* First get the list of tags from the tags table. Then lookup the associated file in the indirect list for each tag, and update it. */ get_nodes_of_tags_table (file_buffer, tags_binding); /* We have the list of tags in file_buffer->tags. Get the list of subfiles from the indirect table. */ { char *start, *end, *line; SUBFILE *subfile; start = indirect_binding->buffer + indirect_binding->start; end = indirect_binding->buffer + indirect_binding->end; line = start; while (line < end) { int colon; colon = string_in_line (":", line); if (colon == -1) break; subfile = (SUBFILE *)xmalloc (sizeof (SUBFILE)); subfile->filename = (char *)xmalloc (colon); strncpy (subfile->filename, line, colon - 1); subfile->filename[colon - 1] = '\0'; subfile->first_byte = (long) atol (line + colon); add_pointer_to_array (subfile, subfiles_index, subfiles, subfiles_slots, 10, SUBFILE *); while (*line++ != '\n'); } } /* If we have successfully built the indirect files table, then merge the information in the two tables. */ if (!subfiles) { free_file_buffer_tags (file_buffer); return; } else { register int tags_index; long header_length; SEARCH_BINDING binding; /* Find the length of the header of the file containing the indirect tags table. This header appears at the start of every file. We want the absolute position of each node within each subfile, so we subtract the start of the containing subfile from the logical position of the node, and then add the length of the header in. */ binding.buffer = file_buffer->contents; binding.start = 0; binding.end = file_buffer->filesize; binding.flags = S_FoldCase; header_length = find_node_separator (&binding); if (header_length == -1) header_length = 0; /* Build the file buffer's list of subfiles. */ { char *containing_dir, *temp; int len_containing_dir; containing_dir = xstrdup (file_buffer->fullpath); temp = (char *) strrchr (containing_dir, '/'); if (temp) *temp = '\0'; len_containing_dir = strlen (containing_dir); for (i = 0; subfiles[i]; i++); file_buffer->subfiles = (char **) xmalloc ((1 + i) * sizeof (char *)); for (i = 0; subfiles[i]; i++) { char *fullpath; fullpath = (char *) xmalloc (2 + strlen (subfiles[i]->filename) + len_containing_dir); sprintf (fullpath, "%s/%s", containing_dir, subfiles[i]->filename); file_buffer->subfiles[i] = fullpath; } file_buffer->subfiles[i] = (char *)NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -