📄 protoize.c
字号:
else if (inp[0] == '/' && outp[-1] == '/') { inp++; continue; } else if (inp[0] == '.' && outp[-1] == '/') { if (!inp[1]) break; else if (inp[1] == '/') { inp += 2; continue; } else if ((inp[1] == '.') && (inp[2] == 0 || inp[2] == '/')) { inp += (inp[2] == '/') ? 3 : 2; outp -= 2; while (outp >= abs_buffer && *outp != '/') outp--; if (outp < abs_buffer) { /* Catch cases like /.. where we try to backup to a point above the absolute root of the logical file system. */ fprintf (stderr, "%s: invalid file name: %s\n", pname, rel_filename); exit (1); } *++outp = '\0'; continue; } } *outp++ = *inp++; } /* On exit, make sure that there is a trailing null, and make sure that the last character of the returned string is *not* a slash. */ *outp = '\0'; if (outp[-1] == '/') *--outp = '\0'; /* Make a copy (in the heap) of the stuff left in the absolutization buffer and return a pointer to the copy. */ return savestring (abs_buffer, outp - abs_buffer);}/* Given a filename (and possibly a directory name from which the filename is relative) return a string which is the shortest possible equivalent for the corresponding full (absolutized) filename. The shortest possible equivalent may be constructed by converting the absolutized filename to be a relative filename (i.e. relative to the actual current working directory). However if a relative filename is longer, then the full absolute filename is returned. KNOWN BUG: Note that "simple-minded" conversion of any given type of filename (either relative or absolute) may not result in a valid equivalent filename if any subpart of the original filename is actually a symbolic link. */static const char *shortpath (cwd, filename) const char *cwd; const char *filename;{ char *rel_buffer; char *rel_buf_p; char *cwd_p = cwd_buffer; char *path_p; int unmatched_slash_count = 0; size_t filename_len = strlen (filename); path_p = abspath (cwd, filename); rel_buf_p = rel_buffer = (char *) xmalloc (filename_len); while (*cwd_p && (*cwd_p == *path_p)) { cwd_p++; path_p++; } if (!*cwd_p && (!*path_p || *path_p == '/')) /* whole pwd matched */ { if (!*path_p) /* input *is* the current path! */ return "."; else return ++path_p; } else { if (*path_p) { --cwd_p; --path_p; while (*cwd_p != '/') /* backup to last slash */ { --cwd_p; --path_p; } cwd_p++; path_p++; unmatched_slash_count++; } /* Find out how many directory levels in cwd were *not* matched. */ while (*cwd_p) if (*cwd_p++ == '/') unmatched_slash_count++; /* Now we know how long the "short name" will be. Reject it if longer than the input. */ if (unmatched_slash_count * 3 + strlen (path_p) >= filename_len) return filename; /* For each of them, put a `../' at the beginning of the short name. */ while (unmatched_slash_count--) { /* Give up if the result gets to be longer than the absolute path name. */ if (rel_buffer + filename_len <= rel_buf_p + 3) return filename; *rel_buf_p++ = '.'; *rel_buf_p++ = '.'; *rel_buf_p++ = '/'; } /* Then tack on the unmatched part of the desired file's name. */ do { if (rel_buffer + filename_len <= rel_buf_p) return filename; } while (*rel_buf_p++ = *path_p++); --rel_buf_p; if (*(rel_buf_p-1) == '/') *--rel_buf_p = '\0'; return rel_buffer; }}/* Lookup the given filename in the hash table for filenames. If it is a new one, then the hash table info pointer will be null. In this case, we create a new file_info record to go with the filename, and we initialize that record with some reasonable values. *//* FILENAME was const, but that causes a warning on AIX when calling stat. That is probably a bug in AIX, but might as well avoid the warning. */static file_info *find_file (filename, do_not_stat) char *filename; int do_not_stat;{ hash_table_entry *hash_entry_p; hash_entry_p = lookup (filename_primary, filename); if (hash_entry_p->fip) return hash_entry_p->fip; else { struct stat stat_buf; file_info *file_p = (file_info *) xmalloc (sizeof (file_info)); /* If we cannot get status on any given source file, give a warning and then just set its time of last modification to infinity. */ if (do_not_stat) stat_buf.st_mtime = (time_t) 0; else { if (my_stat (filename, &stat_buf) == -1) { fprintf (stderr, "%s: %s: can't get status: %s\n", pname, shortpath (NULL, filename), my_strerror(errno)); stat_buf.st_mtime = (time_t) -1; } } hash_entry_p->fip = file_p; file_p->hash_entry = hash_entry_p; file_p->defs_decs = NULL; file_p->mtime = stat_buf.st_mtime; return file_p; }}/* Generate a fatal error because some part of the aux_info file is messed up. */static voidaux_info_corrupted (){ fprintf (stderr, "\n%s: fatal error: aux info file corrupted at line %d\n", pname, current_aux_info_lineno); exit (1);}/* ??? This comment is vague. Say what the condition is for. *//* Check to see that a condition is true. This is kind of like an assert. */static voidcheck_aux_info (cond) int cond;{ if (! cond) aux_info_corrupted ();}/* Given a pointer to the closing right parenthesis for a particular formals list (in an aux_info file) find the corresponding left parenthesis and return a pointer to it. */static const char *find_corresponding_lparen (p) const char *p;{ const char *q; int paren_depth; for (paren_depth = 1, q = p-1; paren_depth; q--) { switch (*q) { case ')': paren_depth++; break; case '(': paren_depth--; break; } } return ++q;}/* Given a line from an aux info file, and a time at which the aux info file it came from was created, check to see if the item described in the line comes from a file which has been modified since the aux info file was created. If so, return non-zero, else return zero. */static intreferenced_file_is_newer (l, aux_info_mtime) const char *l; time_t aux_info_mtime;{ const char *p; file_info *fi_p; char *filename; check_aux_info (l[0] == '/'); check_aux_info (l[1] == '*'); check_aux_info (l[2] == ' '); { const char *filename_start = p = l + 3; while (*p != ':') p++; filename = (char *) alloca ((size_t) (p - filename_start) + 1); strncpy (filename, filename_start, (size_t) (p - filename_start)); filename[p-filename_start] = '\0'; } /* Call find_file to find the file_info record associated with the file which contained this particular def or dec item. Note that this call may cause a new file_info record to be created if this is the first time that we have ever known about this particular file. */ fi_p = find_file (abspath (invocation_filename, filename), 0); return (fi_p->mtime > aux_info_mtime);}/* Given a line of info from the aux_info file, create a new def_dec_info record to remember all of the important information about a function definition or declaration. Link this record onto the list of such records for the particular file in which it occurred in proper (descending) line number order (for now). If there is an identical record already on the list for the file, throw this one away. Doing so takes care of the (useless and troublesome) duplicates which are bound to crop up due to multiple inclusions of any given individual header file. Finally, link the new def_dec record onto the list of such records pertaining to this particular function name. */static voidsave_def_or_dec (l, is_syscalls) const char *l; int is_syscalls;{ const char *p; const char *semicolon_p; def_dec_info *def_dec_p = (def_dec_info *) xmalloc (sizeof (def_dec_info));#ifndef UNPROTOIZE def_dec_p->written = 0;#endif /* !defined (UNPROTOIZE) */ /* Start processing the line by picking off 5 pieces of information from the left hand end of the line. These are filename, line number, new/old/implicit flag (new = ANSI prototype format), definition or declaration flag, and extern/static flag). */ check_aux_info (l[0] == '/'); check_aux_info (l[1] == '*'); check_aux_info (l[2] == ' '); { const char *filename_start = p = l + 3; char *filename; while (*p != ':') p++; filename = (char *) alloca ((size_t) (p - filename_start) + 1); strncpy (filename, filename_start, (size_t) (p - filename_start)); filename[p-filename_start] = '\0'; /* Call find_file to find the file_info record associated with the file which contained this particular def or dec item. Note that this call may cause a new file_info record to be created if this is the first time that we have ever known about this particular file. Note that we started out by forcing all of the base source file names (i.e. the names of the aux_info files with the .X stripped off) into the filenames hash table, and we simultaneously setup file_info records for all of these base file names (even if they may be useless later). The file_info records for all of these "base" file names (properly) act as file_info records for the "original" (i.e. un-included) files which were submitted to gcc for compilation (when the -aux-info option was used). */ def_dec_p->file = find_file (abspath (invocation_filename, filename), is_syscalls); } { const char *line_number_start = ++p; char line_number[10]; while (*p != ':') p++; strncpy (line_number, line_number_start, (size_t) (p - line_number_start)); line_number[p-line_number_start] = '\0'; def_dec_p->line = atoi (line_number); } /* Check that this record describes a new-style, old-style, or implicit definition or declaration. */ p++; /* Skip over the `:'. */ check_aux_info ((*p == 'N') || (*p == 'O') || (*p == 'I')); /* Is this a new style (ANSI prototyped) definition or declaration? */ def_dec_p->prototyped = (*p == 'N');#ifndef UNPROTOIZE /* Is this an implicit declaration? */ def_dec_p->is_implicit = (*p == 'I');#endif /* !defined (UNPROTOIZE) */ p++; check_aux_info ((*p == 'C') || (*p == 'F')); /* Is this item a function definition (F) or a declaration (C). Note that we treat item taken from the syscalls file as though they were function definitions regardless of what the stuff in the file says. */ def_dec_p->is_func_def = ((*p++ == 'F') || is_syscalls);#ifndef UNPROTOIZE def_dec_p->definition = 0; /* Fill this in later if protoizing. */#endif /* !defined (UNPROTOIZE) */ check_aux_info (*p++ == ' '); check_aux_info (*p++ == '*'); check_aux_info (*p++ == '/'); check_aux_info (*p++ == ' ');#ifdef UNPROTOIZE check_aux_info ((!strncmp (p, "static", 6)) || (!strncmp (p, "extern", 6)));#else /* !defined (UNPROTOIZE) */ if (!strncmp (p, "static", 6)) def_dec_p->is_static = -1; else if (!strncmp (p, "extern", 6)) def_dec_p->is_static = 0; else check_aux_info (0); /* Didn't find either `extern' or `static'. */#endif /* !defined (UNPROTOIZE) */ { const char *ansi_start = p; p += 6; /* Pass over the "static" or "extern". */ /* We are now past the initial stuff. Search forward from here to find the terminating semicolon that should immediately follow the entire ANSI format function declaration. */ while (*++p != ';') continue; semicolon_p = p; /* Make a copy of the ansi declaration part of the line from the aux_info file. */ def_dec_p->ansi_decl = dupnstr (ansi_start, (size_t) ((semicolon_p+1) - ansi_start)); /* Backup and point at the final right paren of the final argument list. */ p--;#ifndef UNPROTOIZE def_dec_p->f_list_chain = NULL;#endif /* !defined (UNPROTOIZE) */ while (p != ansi_start && (p[-1] == ' ' || p[-1] == '\t')) p--; if (*p != ')') { free_def_dec (def_dec_p); return; } } /* Now isolate a whole set of formal argument lists, one-by-one. Normally, there will only be one list to isolate, but there could be more. */ def_dec_p->f_list_count = 0; for (;;) { const char *left_paren_p = find_corresponding_lparen (p);#ifndef UNPROTOIZE { f_list_chain_item *cip =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -