[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Help-smalltalk] Problem generating file gtk/Funcs.st while compilin
From: |
Paolo Bonzini |
Subject: |
Re: [Help-smalltalk] Problem generating file gtk/Funcs.st while compiling gst V2.2 |
Date: |
Fri, 22 Sep 2006 14:25:54 +0200 |
User-agent: |
Thunderbird 1.5.0.7 (Macintosh/20060909) |
olivier blanc wrote:
Le vendredi 15 septembre 2006 à 17:58 +0200, Paolo Bonzini a écrit :
Funcs.st : the tile funcs.awk calls function gensub. This function isn't
known, but file snprintfv/gendoc.awk talks about it :
What sould I do ? get the patch fome that file and implement it in the
funcs.awk, or someone of you already modified this ?
I haven't but there is only one line calling gensub, and it can be
replaced by gsub(/[ \t]+/, "", first_line[1]).
That's what I tried, but the generated file file Funcs.st is then
empty...
The attached funcs.awk fixes all the mawk portability problems I could find.
Paolo
#! @AWK@ -f
#######################################################################
#
# Gtk wrapper creation scripts (C function declarations)
#
########################################################################
#######################################################################
#
# Copyright 2001, 2003, 2005, 2006 Free Software Foundation, Inc.
# Written by Paolo Bonzini and Dragomir Milivojevic
#
# This file is part of the GNU Smalltalk class library.
#
# The GNU Smalltalk class library is free software; you can redistribute it
# and/or modify it under the terms of the GNU Lesser General Public License
# as published by the Free Software Foundation; either version 2.1, or (at
# your option) any later version.
#
# The GNU Smalltalk class library is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with the GNU Smalltalk class library; see the file COPYING.LESSER.
# If not, write to the Free Software Foundation, 59 Temple Place - Suite
# 330, Boston, MA 02110-1301, USA.
#
########################################################################
BEGIN {
print "\"Automatically generated, do not edit!\""
FS = "[ (\t]+"
type["void"] = "#void"
type["int"] = "#int"
type["char"] = "#char"
type["wchar_t"] = "#wchar"
type["double"] = "#double"
type["gconstpointer"] = "#cObject"
type["gpointer"] = "#cObject"
type["GStrv"] = "#cObject"
type["va_list"] = "__skip_this__"
type["GCallback"] = "__skip_this__"
type["GClosure"] = "__skip_this__"
type["GCClosure"] = "__skip_this__"
# Skip GLib artifacts
type["GFlags"] = "__skip_this__"
type["GValue"] = "__skip_this__"
type["GIo"] = "__skip_this__"
type["GEnum"] = "__skip_this__"
type["GPointer"] = "__skip_this__"
type["GGstring"] = "__skip_this__"
type["GStrdup"] = "__skip_this__"
type["GTypeClass"] = "__skip_this__"
type["GScanner"] = "__skip_this__"
type["GBoxed"] = "__skip_this__"
type["GSignal"] = "__skip_this__"
type["PangoCoverage"] = "__skip_this__" #FIXME
# FIXME: what about 64-bit architectures?
type["gint8"] = "#int"
type["guint8"] = "#int"
type["gint16"] = "#int"
type["guint16"] = "#int"
type["gint32"] = "#int"
type["guint32"] = "#int"
type["GType"] = "#long"
type["GtkType"] = "#long"
type["gchar"] = "#char"
type["guchar"] = "#int"
type["gunichar"] = "#int"
type["gshort"] = "#int"
type["gushort"] = "#int"
type["glong"] = "#long"
type["gulong"] = "#long"
type["gint"] = "#int"
type["guint"] = "#int"
type["gboolean"] = "#boolean"
type["gfloat"] = "#float"
type["gdouble"] = "#double"
ptr_type["#int"] = "CInt type"
ptr_type["#long"] = "CLong type"
ptr_type["#boolean"] = "CBoolean type"
ptr_type["#float"] = "CFloat type"
ptr_type["#double"] = "CDouble type"
ptr_type["#char"] = "#string"
ptr_type["#wchar"] = "#wstring"
ptr_type["__byte__"] = "#byteArray"
ptr_type["#cObject"] = "#cObject"
# Fix asymmetry
method_regexp = "^g_param_values?_|^g_param_type_|^gtk_file_chooser_"
class["g_param_value_"] = "GParamSpec"
class["g_param_values_"] = "GParamSpec"
class["g_param_type_"] = "GParamSpec"
# Methods that we do not need
method_skip_regexp = "(^$)|(_error_quark$)"
# Not really exact, this belongs in GtkFileChooserWidget too.
# We need a way to do interfaces.
class["gtk_file_chooser_"] = "GtkFileChooserDialog"
}
# Pick the correct case for the class (e.g. CList vs. Clist)
# and decide what will be the prefix for its methods
$1 == "struct" && $2 ~ /^_/ {
name = substr($2, 2)
define_class(name)
}
$0 ~ /^typedef (struct|union)/ && $3 ~ /_(G|Pango|Atk)/ {
gsub(/[_;]/, "", $0)
define_class($4)
}
$1 == "typedef" && $2 ~ /^(G|Pango|Atk)/ {
# Take into account typedefs from a struct named differently.
gsub(/[_;]/, "", $0)
define_class($3)
}
match ($0, /^G_CONST_RETURN[ \t]*/) {
$0 = substr ($0, RLENGTH + 1)
}
match_function_first_line($0) {
gsub(/[ \t]+/, "", first_line[1])
cFuncName = first_line[2]
if (first_line[2] ~ method_skip_regexp)
next
else if (match(first_line[2], method_regexp))
className = class[substr(first_line[2], 1, RLENGTH)]
else if (match (first_line[2], /^(g_)?[a-z]*_/))
className = smalltalkize(toupper(substr(first_line[2], 1, RLENGTH - 1)))
if (tolower(className) in correct_case)
className = correct_case[tolower(className)]
first_line[2] = substr(first_line[2], RLENGTH + 1)
# For types that are not classes, do not create the getType method
if (first_line[2] == "get_type" && (className in type))
next
# Move object creation methods to the class side. We have a single
# special case for an API exception: gtk_ui_manager_new_merge_id
# doesn't make a new ui_manager
creation = first_line[2] ~ /^(newv?|alloc)($|_)/
if (first_line[2] == "new_merge_id")
creation = 0
# Lose some symmetry for the sake of intuitiveness
self = first_line[2] ~ /(^|_)((un)?ref$|(dis)?connect)/
if (match(first_line[2], /^paint_/))
className = "GtkStyle"
if (match(first_line[2], /^draw_/))
className = (className == "Gdk" ? "GdkDrawable" : "GtkStyle")
smalltalkFuncName = smalltalkize(first_line[2])
# create one long string and tokenize it
decl = first_line[1] " " first_line[2] " " first_line[4]
while( match( decl, ";" ) == 0 )
{
getline
for (i = 1; i <= NF; i++)
# Convert arrays to pointers
while( $i ~ /\[[0-9]*\]/ )
{
$i = "*" $i
sub (/\[[0-9]*\]/, "", $i)
}
decl = decl " " $0
}
# Check for non-default visibility
if (decl ~ /G_GNUC_INTERNAL/)
next
# Check for presence of pointers to functions
if (decl ~ /\([ \t]*\*/)
next
gsub (/const[ \t]+/, "", decl)
split( decl, arr )
# tokenize
decl = save_decl = ""
void = 0
strip_variadic = 0
for(i = 1; i in arr; i++) {
last = strip(tst)
tst = arr[i]
if (substr(tst, 1, 3) == "...") {
# remove last argument if it was actually the first variadic argument
if (decl ~ /: first/ && save_decl !~ /: first/) {
strip_variadic = 1
decl = save_decl
}
decl = decl " varargs: varargs"
break
}
if( tst !~ /[,\)]/ )
continue
tst = smalltalkize( strip( tst ) )
if (tst == "void" || last == "void") {
void = 1
break
}
if (decl != "")
{
save_decl = decl
decl = decl " " tst ": " tst
continue
}
if (i < 5 && last == className)
self = 1
if (i >= 5 || !self)
decl = smalltalkFuncName ": " tst
}
argdecl = save_decl = ""
tst = ""
for(i = 1; i in arr; i++)
{
last = tst
tst = arr[i]
if( tst !~ /[,\)]/ )
continue
if (i < 5 && self)
argdecl = argdecl " #self"
else if (substr(tst, 1, 3) == "...")
{
if (strip_variadic)
argdecl = save_decl
argdecl = argdecl " #variadic"
break
}
else if ( index( tst, "," ) > 0 || index( tst, ")" ) > 0 )
{
save_decl = argdecl
argdecl = argdecl " " ctype(last, tst)
}
}
if (creation)
retType = returned(className "*")
else
retType = returned(first_line[1])
if (void)
argdecl = ""
if (decl == "")
decl = smalltalkFuncName
# skip some functions that we don't have bindings for
if (type[className] == "__skip_this__" \
|| classname ~ /^G.*(Func|Notify)$/ \
|| className == "GType" \
|| className == "GtkType" \
|| argdecl ~ /__skip_this__/ \
|| retType == "__skip_this__")
next
# print the declaration
print "!" className (self ? "" : " class") " methodsFor: 'C call-outs'!"
print decl
print " <cCall: '" cFuncName "' returning: " retType
print "\targs: #(" argdecl " )>! !\n"
if (decl == "getType")
print "GLib registerType: " className "!\n"
}
# strips garbage from string
function strip( var )
{
gsub( /[()\\,;*]/, "", var )
gsub( /\[[0-9]*\]/, "", var )
return var
}
function ctype( the_type, name )
{
if (match (the_type, /\*+$/))
{ name = substr (the_type, RSTART) name
the_type = substr (the_type, 1, RSTART - 1)
}
# pointers to pointers are CObject, and pointers to functions have
# a standard naming convention in Gtk+.
if (name ~ /^\*\*/ || the_type ~ /Func$/)
return "#cObject"
pointer = ((name ~ /^\*/) || (name ~ /\[[0-9]*\]/))
res = type[the_type]
if (!pointer || res == "__skip_this__")
{
if (res == "" || res == "__byte__")
res = "#int"
}
else {
res = ptr_type[res]
if (res !~ /^#/)
res = "#cObject"
}
return res
}
function returned( var )
{
pointer = var ~ /\*$/
var = strip(var)
res = type[var]
if (!pointer || res == "__skip_this__")
{
if (res == "")
res = "#int"
}
else {
res = ptr_type[res]
if (res == "")
res = var " type"
}
return res
}
function smalltalkize( res )
{
first = substr (res, 1, 1)
res = tolower( substr (res, 2) )
while (j = index (res, "_")) {
first = first substr(res, 1, j - 1) toupper( substr (res, j + 1, 1))
res = substr (res, j + 2)
}
return first res
}
function define_class(name) {
if (name ~ /(Class|Iface)$/ || name ~ /[^A-Za-z_]/)
return
# Bug report from GTK+ 2.2.2. This can be dropped if it is safe.
if (name == "GParam")
return
correct_case[tolower(name)] = name
prefix = method_prefix(name)
if (prefix in class)
return
method_regexp = method_regexp "|^" prefix
class[prefix] = name
# if object methods turn up on the wrong class (i.e. GtkUIManager on Gtk,
# check prefix here... its probably wrong.
}
function method_prefix(name, i, ch, prev_up)
{
prefix = ""
prev_up = 0
# Initialize so that the heuristic for consecutive uppercase
# characters fires for GObject, GParam, etc.
prev_notup = -2
for (i = 1; i < length (name); i++)
{
ch = substr (name, i, 1)
if (ch >= "A" && ch <= "Z")
{
if (break_word_before_uppercase(name, i, prev_up, prev_notup))
prefix = prefix "_"
prev_up = i
}
else
prev_notup = i
prefix = prefix ch
}
# Add final character.
prefix = prefix substr (name, length (name))
return tolower (prefix) "_"
}
function break_word_before_uppercase(name, cur_index, prev_up, prev_notup)
{
# Always break on uppercase character preceded by lowercase
if (prev_up != cur_index - 1)
return 1
# Never break before the first character
if (prev_up == 0)
return 0
# May break if there are at least three consecutive uppercase chars...
if (cur_index < prev_notup + 3)
return 0
# ...if last char was capitalised, this is, but next isn't.
# This is for things like ui_manager => UIManager amongst others.
ch = substr(name, cur_index + 1, 1)
return ch < "A" || ch > "Z"
}
# emulate gawk match(word, REGEX, first_line)
# where REGEX is /^[ \t]*([a-zA-Z][a-zA-Z0-9]*[
\t\*]+)((g[a-z]*|pango)_[a-zA-Z0-9_]*)[ \t]*(\(.*)/
function match_function_first_line(word) {
if (!match (word, /^[ \t]*[a-zA-Z][a-zA-Z0-9]*[
\t\*]+(g[a-z]*|pango)_[a-zA-Z0-9_]*[ \t]*\(/))
return 0
split ("", first_line)
first_line[4] = substr (word, RSTART + RLENGTH - 1)
word = substr (word, 1, RSTART + RLENGTH - 2)
# Remove spaces
sub (/^[ \t]*/, "", word)
sub (/[ \t]*$/, "", word)
# Extract function name
match (word, /(g[a-z]*|pango)_[a-zA-Z0-9_]*$/)
first_line[1] = substr (word, 1, RSTART - 1)
first_line[2] = substr (word, RSTART)
# Extract package name
match (first_line[2], /^(g[a-z]*|pango)_/)
first_line[3] = substr (first_line[2], 1, RLENGTH - 1)
return 1
}