Professional Documents
Culture Documents
I_amok
2009.04.28
static void
keep_new_line (struct buffer_record *b, char *line_start, size_ t line_len)
record_line_starts 解读。
memchr 的用法如下:
The function searches for the first element of an array of unsigned ch ar, beginning at the
address s with size n, that equals (unsigned char)c. If successful, it returns the address of
the matching element; otherwise, it returns a null pointer.
lines = 0;
line_start = b->buffer;
bytes_left = b->bytes_used;
for (;;)
{
line_end = memchr (line_start, '\n', bytes_left);
if (line_end == NULL)
break;
line_length = line_end - line_start + 1;
keep_new_line (b, line_start, line_length);
bytes_left -= line_length;
line_start = line_end + 1;
lines++;
}
这段代码主要是说在 b->buffer 里搜索 b->bytes_used 长度的数据,看看是否有 newline 符号,如果有,
就调用 keep_new_line 这个数据结构来保存 line_start(指针)和 line_length,并且 lines++
void *
xmemdup (void const *p, size_ t s)
{
return memcpy (xmalloc (s), p, s);
}
memcpy
void *memcpy(void *restrict s1, const void *restrict s2, size_ t n);The function copies the
array of char beginning at the address s2 to the array of char beginning at the address s1
(both of size n). It returns s1. The elements of the arrays can be accessed and stored in
any order.
然后 save_to_hold_area 分别把这两个东西,一个是地址,一个是长度,保存在全局变量
hold_area 和 hold_count 中
然后更新 buffer_record 里面的 num_lines,start_line,first_available
last_line_number,并且返回 lines。
static void
save_buffer (struct buffer_record *buf)
{
struct buffer_record *p;
buf->next = NULL;
buf->curr_line = buf->line_start;
if (head == NULL)
head = buf;
else
{
for (p = head; p->next; p = p->next)
/* Do nothing. */ ;
p->next = buf;
}
}
跟踪的代码就靠这个:
static bool
load_buffer (void)
开始 load 数据了
b = get_new_buffer (bytes_wanted);
bytes_avail = b->bytes_alloc; /* Size of buffer returned. */
p = b->buffer;
如果前面有数据就读取数据到新生成的 buffer_record 里
用的是 memcpy 的方式,copy hold_count 的数据,然后移动 b->buffer 的指针到+hold_count
然后更新 b->bytes_used,减少 bytes_avail,hold_count=0
然后通过
alloc_size = START_SIZE ;
if (alloc_size < min_size )
{
size_ t s = min_size - alloc_size + INCR_SIZE - 1;
alloc_size += s - s % INCR_SIZE ;
}
if (!lines_found)
free_buffer (b);
然后接着指定分配内存大小为 2* b->bytes_alloc
然后清空前面分配的太小内存地址
free_buffer (b); 清空 b->buffer
free (b); 清空 buffer_record
然后继续这个 while 循环
返回真,如果找到一行,返回假,找到 EOF
++(head->first_available);
在 buffer 里查找输入的行号的指针
for (b = head;;)
{
if (linenum < b->start_line + b->num_lines)
最后返回具体的行指针。
如果没有找到符合
if (linenum < b->start_line + b->num_lines)
条件的,就进入下一个 buffer_record 块
b = b->next;
static void
process_line_count (const struct control *p, uintmax_t repetition)
建立一个输出文件,然后用 while 循环
while (linenum++ < last_line_to_save)
save_line_to_file (line);
关闭文件
close_output_file ();
/* Ensure that the line number specified is not 1 greater than
the number of lines in the file. */
if (no_more_lines ())
handle_line_error (p, repetition);
最后一步不知道是干啥的.
static void
process_regexp (struct control *p, uintmax_t repetition)
文件头在./lib/regex.h
/* Search in the string STRING (with length LENGTH) for the pattern
compiled into BUFFER. Start searching at position START, for RANGE
characters. Return the starting position of the match, -1 for no
match, or -2 for an internal error. Also return register
information in REGS (if REGS and BUFFER->no_sub are nonzero). */
为正的时候,就是要往后追加写入的行数(offset)
static_inline void *
x2nrealloc (void *p, size_ t *pn, size_ t s)
{
size_ t n = *pn;
if (! p)
{
if (! n)
{
/* The approximate size to use for initial small allocation
requests, when the invoking code specifies an old size of
ze ro. 64 bytes is the largest "small" request for the
GNU C library malloc. */
enum { DEFAULT_MXFAST = 64 };
n = DEFAULT_MXFAST / s;
n += !n;
}
}
else
{
/* Set N = ceil (1.5 * N) so that progress is made if N == 1.
Check for overflow, so that N * S stays in size_ t range.
The check is slightly conservative, but an exact check isn't
worth the trouble. */
if ((size_t) -1 / 3 * 2 / s <= n)
xalloc_die ();
n += (n + 1) / 2;
}
*pn = n;
return xrealloc (p, n * s);
}
PARAMS 的定义
PARAMS ((prototype))
-- for functions which take a fixed number of arguments. Use this
when declaring the function. When defining the function, write a
K+R style argument list. For example:
在 /usr/include/ansidecl.h 中有说明
同样的头文件里有这样的 define
我还 没 理 解 这 个 x2nrealloc 具体 的 原 理 , 我暂 时 理 解 为 , 他通 过 判 断 controls 的大 小 , 还有
control_allocated 的值来决定是否要增加 controls 的内存分配.... ,每次增加的值为 n += (n + 1)
/ 2; 只有当
control_used == control_allocated 才进行新的分配.这个算法具体有啥意义我还没理解.
原来 ./lib/xalloc.h 注释部分我没有认证看,都有说明
if (! p)
{
if (! n)
所以就是
enum { DEFAULT_MXFAST = 64 };
n = DEFAULT_MXFAST / s;
n += !n;
static void
check_for_offset (struct control *p, const char *str, const char *num)
static void
parse_repeat_count (int argnum, struct control *p, char *str)
这个语句是把{}中的字符形式数字转换成数字类型,并把地址传给&val
/* Extract the regular expression from STR and check for a numeric offset.
STR should start with the regexp delimiter character.
Return a new control record for the regular expression.
ARGNUM is the ARGV index of STR.
Unless IGNORE is true, mark these lines for output. */
if (closing_delim[1])
check_for_offset (p, str, closing_delim + 1);
因为 closing_delim[0]是定界符本身, [1]就是后面紧跟的数字了.
/* Extract the break patterns from args START through ARGC - 1 of ARGV.
After each pattern, check if the next argument is a repeat count. */
static void
parse_patterns (int argc, int start, char **argv)
整个函数是用来分析命令行里的 pattern 的.
更新 :
如果 opt 参数被处理完毕后,第一个可用的参数不是/或者%开头的,那就肯定是指定的行数了.
最后再赋值给 p->lines_required
static size_ t
get_format_prec (char **format_ptr)
static void
get_format_conv_type (char **format_ptr)
get_format_conv_type 中有这样一句话,我开始很纳闷,不知道干嘛的
测试代码如下:
#include <stdio.h>
//打印出第一个指针所指的具体数值
printf ( "%c\n", **array );
//第二个指针的具体数值
printf ("%p\n",*array + 1);
//打印出第二个指针所指的字符
printf ( "%c\n", *(*array+1) );
//做偏移指针的动作
ch=*(*array)++;
//看看偏移后的指针和具体数值
printf ( "%p\n" , *array );
printf ( "%c\n", **array );
return 0;
输出如下:
0x8048538
h
0x8048539
a
after point ++
0x8048539
a
the char is h
可以看到做偏移动作后,字串的第一个位置就后移了.
static size_t
max_out (char *format)
原来 max_out 是在后面的这里使用呢
if (suffix)
filename_space = xmalloc (strlen (prefix) + max_out (suffix) + 2);
就是用来处理后缀文件名的.
只有 [字符]%width.precision[diouxX]
max_out 就是计算这个格式所需要的最小长度.
set_input_file (argv[optind++]);