Re: -fdump-go-spec option does not handle redefinitions
On Wed, Nov 2, 2011 at 6:06 AM, Ian Lance Taylor i...@google.com wrote: The problem with your proposal is that the output would be invalid Go, because it would attempt to define the name _aa twice. However, it does seem plausible that in most scenarios of this type it would be more useful for -fdump-go-spec to generate const _aa = 3 I agree. This patch implements this approach. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline. Thanks, bu this is still not enough to determine corretc IOCTL number :( #defines with arguments are not working at all. Please consider following testcase: --cut here-- #define _IOC_NRBITS8 #define _IOC_TYPEBITS 8 #define _IOC_SIZEBITS 13 #define _IOC_DIRBITS 3 #define _IOC_NRMASK((1 _IOC_NRBITS)-1) #define _IOC_TYPEMASK ((1 _IOC_TYPEBITS)-1) #define _IOC_SIZEMASK ((1 _IOC_SIZEBITS)-1) #define _IOC_DIRMASK ((1 _IOC_DIRBITS)-1) #define _IOC_NRSHIFT 0 #define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS) #define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS) #define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS) /* * Direction bits _IOC_NONE could be 0, but OSF/1 gives it a bit. * And this turns out useful to catch old ioctl numbers in header * files for us. */ #define _IOC_NONE 1U #define _IOC_READ 2U #define _IOC_WRITE 3U #define _IOC(dir,type,nr,size) \ ((unsigned int) \ (((dir) _IOC_DIRSHIFT) | \ ((type) _IOC_TYPESHIFT) |\ ((nr)_IOC_NRSHIFT) | \ ((size) _IOC_SIZESHIFT))) /* used to create numbers */ #define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size)) #define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size)) #define FIOCLEX _IO('f', 1) #define FIONCLEX_IO('f', 2) #define TCGETS _IOR('t', 19, struct termios) #define TCSETS _IOW('t', 20, struct termios) --cut here-- Resulting -fdump-go-spec file: ... const __IOC_NRSHIFT = 0 const __IOC_TYPESHIFT = (__IOC_NRSHIFT+__IOC_NRBITS) const __IOC_SIZESHIFT = (__IOC_TYPESHIFT+__IOC_TYPEBITS) const __IOC_DIRSHIFT = (__IOC_SIZESHIFT+__IOC_SIZEBITS) const __IOC_NONE = 1 const __IOC_READ = 2 const __IOC_WRITE = 3 // unknowndefine FIOCLEX _IO('f', 1) // unknowndefine FIONCLEX _IO('f', 2) // unknowndefine TCGETS _IOR('t', 19, struct termios) // unknowndefine TCSETS _IOW('t', 20, struct termios) Please note missing struct terminfos define, so I understand that TC[GS]ETS is unknown, but FIOCLEX should be fully defined by preceeding definitions. Uros.
Re: -fdump-go-spec option does not handle redefinitions
Uros Bizjak ubiz...@gmail.com writes: #defines with arguments are not working at all. Please consider following testcase: You're right: this approach doesn't work for preprocessor macros with arguments. Making those work via this approach would be much much harder. Please note missing struct terminfos define, so I understand that TC[GS]ETS is unknown, but FIOCLEX should be fully defined by preceeding definitions. Fortunately, the value of FIOCLEX is irrelevant. And as you say, this approach can't work for TCGETS anyhow. So let's take a different approach. This patch drops the use of TCGETS and TCSETS entirely. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline. Ian diff -r 39e671bf216d libgo/go/exp/terminal/terminal.go --- a/libgo/go/exp/terminal/terminal.go Wed Nov 02 08:58:28 2011 -0700 +++ b/libgo/go/exp/terminal/terminal.go Wed Nov 02 09:42:23 2011 -0700 @@ -17,7 +17,6 @@ import ( os syscall - unsafe ) // State contains the state of a terminal. @@ -28,7 +27,7 @@ // IsTerminal returns true if the given file descriptor is a terminal. func IsTerminal(fd int) bool { var termios syscall.Termios - _, _, e := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TCGETS), uintptr(unsafe.Pointer(termios)), 0, 0, 0) + e := syscall.Tcgetattr(fd, termios) return e == 0 } @@ -37,14 +36,14 @@ // restored. func MakeRaw(fd int) (*State, os.Error) { var oldState State - if _, _, e := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TCGETS), uintptr(unsafe.Pointer(oldState.termios)), 0, 0, 0); e != 0 { + if e := syscall.Tcgetattr(fd, oldState.termios); e != 0 { return nil, os.Errno(e) } newState := oldState.termios newState.Iflag ^= syscall.ISTRIP | syscall.INLCR | syscall.ICRNL | syscall.IGNCR | syscall.IXON | syscall.IXOFF newState.Lflag ^= syscall.ECHO | syscall.ICANON | syscall.ISIG - if _, _, e := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TCSETS), uintptr(unsafe.Pointer(newState)), 0, 0, 0); e != 0 { + if e := syscall.Tcsetattr(fd, syscall.TCSANOW, newState); e != 0 { return nil, os.Errno(e) } @@ -54,7 +53,7 @@ // Restore restores the terminal connected to the given file descriptor to a // previous state. func Restore(fd int, state *State) os.Error { - _, _, e := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TCSETS), uintptr(unsafe.Pointer(state.termios)), 0, 0, 0) + e := syscall.Tcsetattr(fd, syscall.TCSANOW, state.termios) return os.Errno(e) } @@ -63,18 +62,18 @@ // returned does not include the \n. func ReadPassword(fd int) ([]byte, os.Error) { var oldState syscall.Termios - if _, _, e := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TCGETS), uintptr(unsafe.Pointer(oldState)), 0, 0, 0); e != 0 { + if e := syscall.Tcgetattr(fd, oldState); e != 0 { return nil, os.Errno(e) } newState := oldState newState.Lflag ^= syscall.ECHO - if _, _, e := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TCSETS), uintptr(unsafe.Pointer(newState)), 0, 0, 0); e != 0 { + if e := syscall.Tcsetattr(fd, syscall.TCSANOW, newState); e != 0 { return nil, os.Errno(e) } defer func() { - syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TCSETS), uintptr(unsafe.Pointer(oldState)), 0, 0, 0) + syscall.Tcsetattr(fd, syscall.TCSANOW, oldState) }() var buf [16]byte diff -r 39e671bf216d libgo/go/syscall/libcall_posix.go --- a/libgo/go/syscall/libcall_posix.go Wed Nov 02 08:58:28 2011 -0700 +++ b/libgo/go/syscall/libcall_posix.go Wed Nov 02 09:42:23 2011 -0700 @@ -377,3 +377,9 @@ tv.Usec = Timeval_usec_t(nsec % 1e9 / 1e3) return } + +//sysnb Tcgetattr(fd int, p *Termios) (errno int) +//tcgetattr(fd int, p *Termios) int + +//sys Tcsetattr(fd int, actions int, p *Termios) (errno int) +//tcsetattr(fd int, actions int, p *Termios) int
Re: -fdump-go-spec option does not handle redefinitions
Uros Bizjak ubiz...@gmail.com writes: The problem with your proposal is that the output would be invalid Go, because it would attempt to define the name _aa twice. However, it does seem plausible that in most scenarios of this type it would be more useful for -fdump-go-spec to generate const _aa = 3 I agree. This patch implements this approach. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline. Ian 2011-11-01 Ian Lance Taylor i...@google.com * godump.c (struct macro_hash_value): Define. (macro_hash_hashval): New static function. (macro_hash_eq, macro_hash_del): New static functions. (go_define): Use macro_hash_value to store values in macro_hash. Replace an old value on a redefinition. Don't print anything to go_dump_file. (go_undef): Delete the entry from the hash table. (go_output_typedef): For an enum, use macro_hash_value, and don't print anything to go_dump_file. (go_print_macro): New static function. (go_finish): Traverse macro_hash with go_print_macro. (dump_go_spec_init): Update macro_hash creation for macro_hash_value. Index: godump.c === --- godump.c (revision 180342) +++ godump.c (working copy) @@ -62,7 +62,47 @@ static GTY(()) VEC(tree,gc) *queue; static htab_t macro_hash; -/* For the hash tables. */ +/* The type of a value in macro_hash. */ + +struct macro_hash_value +{ + /* The name stored in the hash table. */ + char *name; + /* The value of the macro. */ + char *value; +}; + +/* Calculate the hash value for an entry in the macro hash table. */ + +static hashval_t +macro_hash_hashval (const void *val) +{ + const struct macro_hash_value *mhval = (const struct macro_hash_value *) val; + return htab_hash_string (mhval-name); +} + +/* Compare values in the macro hash table for equality. */ + +static int +macro_hash_eq (const void *v1, const void *v2) +{ + const struct macro_hash_value *mhv1 = (const struct macro_hash_value *) v1; + const struct macro_hash_value *mhv2 = (const struct macro_hash_value *) v2; + return strcmp (mhv1-name, mhv2-name) == 0; +} + +/* Free values deleted from the macro hash table. */ + +static void +macro_hash_del (void *v) +{ + struct macro_hash_value *mhv = (struct macro_hash_value *) v; + XDELETEVEC (mhv-name); + XDELETEVEC (mhv-value); + XDELETE (mhv); +} + +/* For the string hash tables. */ static int string_hash_eq (const void *y1, const void *y2) @@ -77,10 +117,12 @@ go_define (unsigned int lineno, const ch { const char *p; const char *name_end; + size_t out_len; char *out_buffer; char *q; bool saw_operand; bool need_operand; + struct macro_hash_value *mhval; char *copy; hashval_t hashval; void **slot; @@ -105,17 +147,17 @@ go_define (unsigned int lineno, const ch memcpy (copy, buffer, name_end - buffer); copy[name_end - buffer] = '\0'; + mhval = XNEW (struct macro_hash_value); + mhval-name = copy; + mhval-value = NULL; + hashval = htab_hash_string (copy); - slot = htab_find_slot_with_hash (macro_hash, copy, hashval, NO_INSERT); - if (slot != NULL) -{ - XDELETEVEC (copy); - return; -} + slot = htab_find_slot_with_hash (macro_hash, mhval, hashval, NO_INSERT); /* For simplicity, we force all names to be hidden by adding an initial underscore, and let the user undo this as needed. */ - out_buffer = XNEWVEC (char, strlen (p) * 2 + 1); + out_len = strlen (p) * 2 + 1; + out_buffer = XNEWVEC (char, out_len); q = out_buffer; saw_operand = false; need_operand = false; @@ -141,6 +183,7 @@ go_define (unsigned int lineno, const ch don't worry about them. */ const char *start; char *n; + struct macro_hash_value idval; if (saw_operand) goto unknown; @@ -151,8 +194,9 @@ go_define (unsigned int lineno, const ch n = XALLOCAVEC (char, p - start + 1); memcpy (n, start, p - start); n[p - start] = '\0'; - slot = htab_find_slot (macro_hash, n, NO_INSERT); - if (slot == NULL || *slot == NULL) + idval.name = n; + idval.value = NULL; + if (htab_find (macro_hash, idval) == NULL) { /* This is a reference to a name which was not defined as a macro. */ @@ -382,18 +426,30 @@ go_define (unsigned int lineno, const ch if (need_operand) goto unknown; + gcc_assert ((size_t) (q - out_buffer) out_len); *q = '\0'; - slot = htab_find_slot_with_hash (macro_hash, copy, hashval, INSERT); - *slot = copy; + mhval-value = out_buffer; - fprintf (go_dump_file, const _%s = %s\n, copy, out_buffer); + if (slot == NULL) +{ + slot = htab_find_slot_with_hash (macro_hash, mhval, hashval, INSERT); + gcc_assert (slot != NULL *slot == NULL); +} + else +{ + if (*slot != NULL) + macro_hash_del (*slot); +} + + *slot = mhval; -