📄 nodes.c
字号:
free (containing_dir); } /* For each node in the file's tags table, remember the starting position. */ for (tags_index = 0; (entry = file_buffer->tags[tags_index]); tags_index++) { for (i = 0; subfiles[i] && entry->nodestart >= subfiles[i]->first_byte; i++); /* If the Info file containing the indirect tags table is malformed, then give up. */ if (!i) { /* The Info file containing the indirect tags table is malformed. Give up. */ for (i = 0; subfiles[i]; i++) { free (subfiles[i]->filename); free (subfiles[i]); free (file_buffer->subfiles[i]); } file_buffer->subfiles = (char **)NULL; free_file_buffer_tags (file_buffer); return; } /* SUBFILES[i] is the index of the first subfile whose logical first byte is greater than the logical offset of this node's starting position. This means that the subfile directly preceding this one is the one containing the node. */ entry->filename = file_buffer->subfiles[i - 1]; entry->nodestart -= subfiles[i -1]->first_byte; entry->nodestart += header_length; entry->nodelen = -1; } /* We have successfully built the tags table. Remember that it was indirect. */ file_buffer->flags |= N_TagsIndirect; } /* Free the structures assigned to SUBFILES. Free the names as well as the structures themselves, then finally, the array. */ for (i = 0; subfiles[i]; i++) { free (subfiles[i]->filename); free (subfiles[i]); } free (subfiles);}/* Return the node from FILE_BUFFER which matches NODENAME by searching the tags table in FILE_BUFFER. If the node could not be found, return a NULL pointer. */static NODE *info_node_of_file_buffer_tags (file_buffer, nodename) FILE_BUFFER *file_buffer; char *nodename;{ register int i; TAG *tag; for (i = 0; (tag = file_buffer->tags[i]); i++) if (strcmp (nodename, tag->nodename) == 0) { FILE_BUFFER *subfile; subfile = info_find_file_internal (tag->filename, INFO_NO_TAGS); if (!subfile) return ((NODE *)NULL); if (!subfile->contents) { info_reload_file_buffer_contents (subfile); if (!subfile->contents) return ((NODE *)NULL); } /* If we were able to find this file and load it, then return the node within it. */ { NODE *node; node = (NODE *)xmalloc (sizeof (NODE)); node->filename = (subfile->fullpath); node->nodename = tag->nodename; node->contents = subfile->contents + tag->nodestart; node->flags = 0; node->parent = (char *)NULL; if (file_buffer->flags & N_HasTagsTable) { node->flags |= N_HasTagsTable; if (file_buffer->flags & N_TagsIndirect) { node->flags |= N_TagsIndirect; node->parent = file_buffer->fullpath; } } if (subfile->flags & N_IsCompressed) node->flags |= N_IsCompressed; /* If TAG->nodelen hasn't been calculated yet, then we aren't in a position to trust the entry pointer. Adjust things so that ENTRY->nodestart gets the exact address of the start of the node separator which starts this node, and NODE->contents gets the address of the line defining this node. If we cannot do that, the node isn't really here. */ if (tag->nodelen == -1) { int min, max; char *node_sep; SEARCH_BINDING node_body; char *buff_end; min = max = DEFAULT_INFO_FUDGE; if (tag->nodestart < DEFAULT_INFO_FUDGE) min = tag->nodestart; if (DEFAULT_INFO_FUDGE > (subfile->filesize - tag->nodestart)) max = subfile->filesize - tag->nodestart; /* NODE_SEP gets the address of the separator which defines this node, or (char *)NULL if the node wasn't found. NODE->contents is side-effected to point to right after the separator. */ node_sep = adjust_nodestart (node, min, max); if (node_sep == (char *)NULL) { free (node); return ((NODE *)NULL); } /* Readjust tag->nodestart. */ tag->nodestart = node_sep - subfile->contents; /* Calculate the length of the current node. */ buff_end = subfile->contents + subfile->filesize; node_body.buffer = node->contents; node_body.start = 0; node_body.end = buff_end - node_body.buffer; node_body.flags = 0; tag->nodelen = get_node_length (&node_body); } else { /* Since we know the length of this node, we have already adjusted tag->nodestart to point to the exact start of it. Simply skip the node separator. */ node->contents += skip_node_separator (node->contents); } node->nodelen = tag->nodelen; return (node); } } /* There was a tag table for this file, and the node wasn't found. Return NULL, since this file doesn't contain the desired node. */ return ((NODE *)NULL);}/* **************************************************************** *//* *//* Managing file_buffers, nodes, and tags. *//* *//* **************************************************************** *//* Create a new, empty file buffer. */FILE_BUFFER *make_file_buffer (){ FILE_BUFFER *file_buffer; file_buffer = (FILE_BUFFER *)xmalloc (sizeof (FILE_BUFFER)); file_buffer->filename = file_buffer->fullpath = (char *)NULL; file_buffer->contents = (char *)NULL; file_buffer->tags = (TAG **)NULL; file_buffer->subfiles = (char **)NULL; file_buffer->tags_slots = 0; file_buffer->flags = 0; return (file_buffer);}/* Add FILE_BUFFER to our list of already loaded info files. */static voidremember_info_file (file_buffer) FILE_BUFFER *file_buffer;{ int i; for (i = 0; info_loaded_files && info_loaded_files[i]; i++) ; add_pointer_to_array (file_buffer, i, info_loaded_files, info_loaded_files_slots, 10, FILE_BUFFER *);}/* Forget the contents, tags table, nodes list, and names of FILENAME. */static voidforget_info_file (filename) char *filename;{ register int i; FILE_BUFFER *file_buffer; if (!info_loaded_files) return; for (i = 0; (file_buffer = info_loaded_files[i]); i++) if ((strcmp (filename, file_buffer->filename) == 0) || (strcmp (filename, file_buffer->fullpath) == 0)) { free (file_buffer->filename); free (file_buffer->fullpath); if (file_buffer->contents) free (file_buffer->contents); /* Note that free_file_buffer_tags () also kills the subfiles list, since the subfiles list is only of use in conjunction with tags. */ free_file_buffer_tags (file_buffer); while ((info_loaded_files[i] = info_loaded_files[++i])) ; break; }}/* Free the tags (if any) associated with FILE_BUFFER. */static voidfree_file_buffer_tags (file_buffer) FILE_BUFFER *file_buffer;{ register int i; if (file_buffer->tags) { register TAG *tag; for (i = 0; (tag = file_buffer->tags[i]); i++) free_info_tag (tag); free (file_buffer->tags); file_buffer->tags = (TAG **)NULL; file_buffer->tags_slots = 0; } if (file_buffer->subfiles) { for (i = 0; file_buffer->subfiles[i]; i++) free (file_buffer->subfiles[i]); free (file_buffer->subfiles); file_buffer->subfiles = (char **)NULL; }}/* Free the data associated with TAG, as well as TAG itself. */static voidfree_info_tag (tag) TAG *tag;{ free (tag->nodename); /* We don't free tag->filename, because that filename is part of the subfiles list for the containing FILE_BUFFER. free_info_tags () will free the subfiles when it is appropriate. */ free (tag);}/* Load the contents of FILE_BUFFER->contents. This function is called when a file buffer was loaded, and then in order to conserve memory, the file buffer's contents were freed and the pointer was zero'ed. Note that the file was already loaded at least once successfully, so the tags and/or nodes members are still correctly filled. */static voidinfo_reload_file_buffer_contents (fb) FILE_BUFFER *fb;{#if defined (HANDLE_MAN_PAGES) /* If this is the magic manpage node, don't try to reload, just give up. */ if (fb->flags & N_IsManPage) return;#endif fb->flags &= ~N_IsCompressed; /* Let the filesystem do all the work for us. */ fb->contents = filesys_read_info_file (fb->fullpath, &(fb->filesize), &(fb->finfo)); if (fb->filesize != (long) (fb->finfo.st_size)) fb->flags |= N_IsCompressed;}/* Return the actual starting memory location of NODE, side-effecting NODE->contents. MIN and MAX are bounds for a search if one is necessary. Because of the way that tags are implemented, the physical nodestart may not actually be where the tag says it is. If that is the case, but the node was found anyway, set N_UpdateTags in NODE->flags. If the node is found, return non-zero. NODE->contents is returned positioned right after the node separator that precedes this node, while the return value is position directly on the separator that precedes this node. If the node could not be found, return a NULL pointer. */static char *adjust_nodestart (node, min, max) NODE *node; int min, max;{ long position; SEARCH_BINDING node_body; /* Define the node body. */ node_body.buffer = node->contents; node_body.start = 0; node_body.end = max; node_body.flags = 0; /* Try the optimal case first. Who knows? This file may actually be formatted (mostly) correctly. */ if (node_body.buffer[0] != INFO_COOKIE && min > 2) node_body.buffer -= 3; position = find_node_separator (&node_body); /* If we found a node start, then check it out. */ if (position != -1) { int sep_len; sep_len = skip_node_separator (node->contents); /* If we managed to skip a node separator, then check for this node being the right one. */ if (sep_len != 0) { char *nodedef, *nodestart; int offset; nodestart = node_body.buffer + position + sep_len; nodedef = nodestart; offset = string_in_line (INFO_NODE_LABEL, nodedef); if (offset != -1) { nodedef += offset; nodedef += skip_whitespace (nodedef); offset = skip_node_characters (nodedef, DONT_SKIP_NEWLINES); if ((offset == strlen (node->nodename)) && (strncmp (node->nodename, nodedef, offset) == 0)) { node->contents = nodestart; return (node_body.buffer + position); } } } } /* Oh well, I guess we have to try to find it in a larger area. */ node_body.buffer = node->contents - min; node_body.start = 0; node_body.end = min + max; node_body.flags = 0; position = find_node_in_binding (node->nodename, &node_body); /* If the node couldn't be found, we lose big. */ if (position == -1) return ((char *)NULL); /* Otherwise, the node was found, but the tags table could need updating (if we used a tag to get here, that is). Set the flag in NODE->flags. */ node->contents = node_body.buffer + position; node->contents += skip_node_separator (node->contents); if (node->flags & N_HasTagsTable) node->flags |= N_UpdateTags; return (node_body.buffer + position);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -