📄 protoize.c
字号:
/* Protoize program - Original version by Ron Guilmette at MCC. Copyright (C) 1989, 1992 Free Software Foundation, Inc.This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING. If not, write tothe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. *//* Any reasonable C++ compiler should have all of the same features as __STDC__ plus more, so make sure that __STDC__ is defined if __cplusplus is defined. */#if defined(__cplusplus) && !defined(__STDC__)#define __STDC__ 1#endif /* defined(__cplusplus) && !defined(__STDC__) */#if defined(__GNUC__) || defined (__GNUG__)#define VOLATILE volatile#else#define VOLATILE#endif#ifndef __STDC__#define const#define volatile#endif#include "config.h"#if 0/* Users are not supposed to use _POSIX_SOURCE to say the system is a POSIX system. That is not what _POSIX_SOURCE means! -- rms */ /* If the user asked for POSIX via _POSIX_SOURCE, turn on POSIX code. */#if defined(_POSIX_SOURCE) && !defined(POSIX)#define POSIX#endif#endif /* 0 */#ifdef POSIX /* We should be able to define _POSIX_SOURCE unconditionally, but some systems respond in buggy ways to it, including SunOS 4.1.1. Which we don't classify as POSIX. *//* In case this is a POSIX system with an ANSI C compiler, ask for definition of all POSIX facilities. */#undef _POSIX_SOURCE#define _POSIX_SOURCE#endif#include <stdio.h>#include <ctype.h>#include <errno.h>#include <sys/types.h>#include <sys/stat.h>#ifdef POSIX#include <dirent.h>#else#include <sys/dir.h>#endif#include <setjmp.h>#include "gvarargs.h"/* Include getopt.h for the sake of getopt_long. We don't need the declaration of getopt, and it could conflict with something from a system header file, so effectively nullify that. */#define getopt getopt_loser#include "getopt.h"#undef getoptextern int errno;extern char *sys_errlist[];extern char *version_string;/* Systems which are compatible only with POSIX 1003.1-1988 (but *not* with POSIX 1003.1-1990), e.g. Ultrix 4.2, might not have const qualifiers in the prototypes in the system include files. Unfortunately, this can lead to GCC issuing lots of warnings for calls to the following functions. To eliminate these warnings we provide the following #defines. */#define my_access(file,flag) access((char *)file, flag)#define my_stat(file,pkt) stat((char *)file, pkt)#define my_execvp(prog,argv) execvp((char *)prog, (char **)argv)#define my_link(file1, file2) link((char *)file1, (char *)file2)#define my_unlink(file) unlink((char *)file)#define my_open(file, mode, flag) open((char *)file, mode, flag)#define my_chmod(file, mode) chmod((char *)file, mode)extern char *getpwd ();/* Aliases for pointers to void. These were made to facilitate compilation with old brain-dead DEC C compilers which didn't properly grok `void*' types. */#ifdef __STDC__typedef void * pointer_type;typedef const void * const_pointer_type;#elsetypedef char * pointer_type;typedef char * const_pointer_type;#endif#if defined(POSIX)#include <stdlib.h>#include <unistd.h>#include <signal.h>#include <fcntl.h>#include <string.h>#else /* !defined(POSIX) */#define R_OK 4 /* Test for Read permission */#define W_OK 2 /* Test for Write permission */#define X_OK 1 /* Test for eXecute permission */#define F_OK 0 /* Test for existence of File */#define O_RDONLY 0#define O_WRONLY 1/* Declaring stat or __flsbuf with a prototype causes conflicts with system headers on some systems. */#ifndef abortextern VOLATILE void abort ();#endifextern int kill ();extern int creat ();#if 0 /* These conflict with stdio.h on some systems. */extern int fprintf (FILE *, const char *, ...);extern int printf (const char *, ...);extern int open (const char *, int, ...);#endif /* 0 */extern void exit ();extern pointer_type malloc ();extern pointer_type realloc ();extern void free ();extern int read ();extern int write ();extern int close ();extern int fflush ();extern int atoi ();extern int puts ();extern int fputs ();extern int fputc ();extern int link ();extern int unlink ();extern int access ();extern int execvp ();#ifndef setjmpextern int setjmp ();#endif#ifndef longjmpextern void longjmp ();#endifextern char * strcat ();extern int strcmp ();extern char * strcpy ();#if 0 /* size_t from sys/types.h may fail to match GCC. If so, we would get a warning from this. */extern size_t strlen ()#endifextern int strncmp ();extern char * strncpy ();extern char * rindex ();/* Fork is not declared because the declaration caused a conflict on the HPPA. */#if !(defined (USG) || defined (VMS))#define fork vfork#endif /* (defined (USG) || defined (VMS)) */#endif /* !defined (POSIX) *//* Look for these where the `const' qualifier is intentionally cast aside. */#define NONCONST/* Define a STRINGIFY macro that's right for ANSI or traditional C. */#ifdef __STDC__#define STRINGIFY(STRING) #STRING#else#define STRINGIFY(STRING) "STRING"#endif/* Define a default place to find the SYSCALLS.X file. */#ifndef STD_PROTO_DIR#define STD_PROTO_DIR "/usr/local/lib"#endif /* !defined (STD_PROTO_DIR) *//* Suffix of aux_info files. */static const char * const aux_info_suffix = ".X";/* String to attach to filenames for saved versions of original files. */static const char * const save_suffix = ".save";#ifndef UNPROTOIZE/* File name of the file which contains descriptions of standard system routines. Note that we never actually do anything with this file per se, but we do read in its corresponding aux_info file. */static const char syscalls_filename[] = "SYSCALLS.c";/* Default place to find the above file. */static const char * const default_syscalls_dir = STD_PROTO_DIR;/* Variable to hold the complete absolutized filename of the SYSCALLS.c.X file. */static char * syscalls_absolute_filename;#endif /* !defined (UNPROTOIZE) *//* Type of the structure that holds information about macro unexpansions. */struct unexpansion_struct { const char *expanded; const char *contracted;};typedef struct unexpansion_struct unexpansion;/* A table of conversions that may need to be made for some (stupid) older operating systems where these types are preprocessor macros rather than typedefs (as they really ought to be). WARNING: The contracted forms must be as small (or smaller) as the expanded forms, or else havoc will ensue. */static const unexpansion unexpansions[] = { { "struct _iobuf", "FILE" }, { 0, 0 }};/* The number of "primary" slots in the hash tables for filenames and for function names. This can be as big or as small as you like, except that it must be a power of two. */#define HASH_TABLE_SIZE (1 << 9)/* Bit mask to use when computing hash values. */static const int hash_mask = (HASH_TABLE_SIZE - 1);/* Make a table of default system include directories just as it is done in cccp.c. */#ifndef STANDARD_INCLUDE_DIR#define STANDARD_INCLUDE_DIR "/usr/include"#endif#ifndef LOCAL_INCLUDE_DIR#define LOCAL_INCLUDE_DIR "/usr/local/include"#endifstruct default_include { const char *fname; int cplusplus; } include_defaults[]#ifdef INCLUDE_DEFAULTS = INCLUDE_DEFAULTS;#else = { /* Pick up GNU C++ specific include files. */ { GPLUSPLUS_INCLUDE_DIR, 1}, { GCC_INCLUDE_DIR, 0},#ifdef CROSS_COMPILE /* For cross-compilation, this dir name is generated automatically in Makefile.in. */ { CROSS_INCLUDE_DIR, 0 },#else /* not CROSS_COMPILE */ { LOCAL_INCLUDE_DIR, 0}, /* Some systems have an extra dir of include files. */#ifdef SYSTEM_INCLUDE_DIR { SYSTEM_INCLUDE_DIR, 0},#endif { STANDARD_INCLUDE_DIR, 0},#endif /* not CROSS_COMPILE */ { 0, 0} };#endif /* no INCLUDE_DEFAULTS *//* Datatype for lists of directories or filenames. */struct string_list{ char *name; struct string_list *next;};/* List of directories in which files should be converted. */struct string_list *directory_list;/* List of file names which should not be converted. A file is excluded if the end of its name, following a /, matches one of the names in this list. */struct string_list *exclude_list;/* The name of the other style of variable-number-of-parameters functions (i.e. the style that we want to leave unconverted because we don't yet know how to convert them to this style. This string is used in warning messages. *//* Also define here the string that we can search for in the parameter lists taken from the .X files which will unambiguously indicate that we have found a varargs style function. */#ifdef UNPROTOIZEstatic const char * const other_var_style = "stdarg";#else /* !defined (UNPROTOIZE) */static const char * const other_var_style = "varargs";/* Note that this is a string containing the expansion of va_alist. But in `main' we discard all but the first token. */static const char *varargs_style_indicator = STRINGIFY (va_alist);#endif /* !defined (UNPROTOIZE) *//* The following two types are used to create hash tables. In this program, there are two hash tables which are used to store and quickly lookup two different classes of strings. The first type of strings stored in the first hash table are absolute filenames of files which protoize needs to know about. The second type of strings (stored in the second hash table) are function names. It is this second class of strings which really inspired the use of the hash tables, because there may be a lot of them. */typedef struct hash_table_entry_struct hash_table_entry;/* Do some typedefs so that we don't have to write "struct" so often. */typedef struct def_dec_info_struct def_dec_info;typedef struct file_info_struct file_info;typedef struct f_list_chain_item_struct f_list_chain_item;/* In the struct below, note that the "_info" field has two different uses depending on the type of hash table we are in (i.e. either the filenames hash table or the function names hash table). In the filenames hash table the info fields of the entries point to the file_info struct which is associated with each filename (1 per filename). In the function names hash table, the info field points to the head of a singly linked list of def_dec_info entries which are all defs or decs of the function whose name is pointed to by the "symbol" field. Keeping all of the defs/decs for a given function name on a special list specifically for that function name makes it quick and easy to find out all of the important information about a given (named) function. */struct hash_table_entry_struct { hash_table_entry * hash_next; /* -> to secondary entries */ const char * symbol; /* -> to the hashed string */ union { const def_dec_info * _ddip; file_info * _fip; } _info;};#define ddip _info._ddip#define fip _info._fip/* Define a type specifically for our two hash tables. */typedef hash_table_entry hash_table[HASH_TABLE_SIZE];/* The following struct holds all of the important information about any single filename (e.g. file) which we need to know about. */struct file_info_struct { const hash_table_entry * hash_entry; /* -> to associated hash entry */ const def_dec_info * defs_decs; /* -> to chain of defs/decs */ time_t mtime; /* Time of last modification. */};/* Due to the possibility that functions may return pointers to functions, (which may themselves have their own parameter lists) and due to the fact that returned pointers-to-functions may be of type "pointer-to- function-returning-pointer-to-function" (ad nauseum) we have to keep an entire chain of ANSI style formal parameter lists for each function. Normally, for any given function, there will only be one formals list on the chain, but you never know. Note that the head of each chain of formals lists is pointed to by the `f_list_chain' field of the corresponding def_dec_info record. For any given chain, the item at the head of the chain is the *leftmost* parameter list seen in the actual C language function declaration. If there are other members of the chain, then these are linked in left-to-right order from the head of the chain. */struct f_list_chain_item_struct { const f_list_chain_item * chain_next; /* -> to next item on chain */ const char * formals_list; /* -> to formals list string */};/* The following struct holds all of the important information about any single function definition or declaration which we need to know about. Note that for unprotoize we don't need to know very much because we never even create records for stuff that we don't intend to convert (like for instance defs and decs which are already in old K&R format and "implicit" function declarations). */struct def_dec_info_struct { const def_dec_info * next_in_file; /* -> to rest of chain for file */ file_info * file; /* -> file_info for containing file */ int line; /* source line number of def/dec */ const char * ansi_decl; /* -> left end of ansi decl */ hash_table_entry * hash_entry; /* -> hash entry for function name */ unsigned int is_func_def; /* = 0 means this is a declaration */ const def_dec_info * next_for_func; /* -> to rest of chain for func name */ unsigned int f_list_count; /* count of formals lists we expect */ char prototyped; /* = 0 means already prototyped */#ifndef UNPROTOIZE const f_list_chain_item * f_list_chain; /* -> chain of formals lists */ const def_dec_info * definition; /* -> def/dec containing related def */ char is_static; /* = 0 means visibility is "extern" */ char is_implicit; /* != 0 for implicit func decl's */ char written; /* != 0 means written for implicit */#else /* !defined (UNPROTOIZE) */ const char * formal_names; /* -> to list of names of formals */ const char * formal_decls; /* -> to string of formal declarations */#endif /* !defined (UNPROTOIZE) */};/* Pointer to the tail component of the filename by which this program was invoked. Used everywhere in error and warning messages. */static const char *pname;/* Error counter. Will be non-zero if we should give up at the next convenient stopping point. */static int errors = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -