root/lang/pascal/xpidlpas/xpidlpas_stdcall.c

Revision 4249, 9.6 kB (checked in by plus7, 12 months ago)

initial import

  • Property svn:executable set to *
Line 
1/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: NPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Netscape Public License
6 * Version 1.1 (the "License"); you may not use this file except in
7 * compliance with the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/NPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is mozilla.org code.
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *   Itou Takanori <necottie@nesitive.net>
24 *
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the NPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the NPL, the GPL or the LGPL.
36 *
37 * ***** END LICENSE BLOCK ***** */
38
39/*
40 * Generate XPCOM headers from XPIDL.
41 */
42
43#include "xpidlpas.h"
44#include <ctype.h>
45
46static gboolean write_method_signature(IDL_tree method_tree, FILE *outfile,
47                                       const char *className);
48static gboolean write_attr_accessor(IDL_tree attr_tree, FILE * outfile,
49                                    gboolean getter,
50                                    const char *className);
51
52/*
53 * An attribute declaration looks like:
54 *
55 * [ IDL_ATTR_DCL]
56 *   - param_type_spec [IDL_TYPE_* or NULL for void]
57 *   - simple_declarations [IDL_LIST]
58 *     - data [IDL_IDENT]
59 *     - next [IDL_LIST or NULL if no more idents]
60 *       - data [IDL_IDENT]
61 */
62
63#define ATTR_IDENT(tree) (IDL_IDENT(IDL_LIST(IDL_ATTR_DCL(tree).simple_declarations).data))
64#define ATTR_TYPE_DECL(tree) (IDL_ATTR_DCL(tree).param_type_spec)
65#define ATTR_TYPE(tree) (IDL_NODE_TYPE(ATTR_TYPE_DECL(tree)))
66
67static gboolean
68write_attr_accessor(IDL_tree attr_tree, FILE * outfile,
69                    gboolean getter, const char *className)
70{
71    char *attrname = ATTR_IDENT(attr_tree).str;
72
73    fprintf(outfile, "function %cet%c%s(",
74            getter ? 'G' : 'S',
75            toupper(*attrname), attrname + 1);
76    /* Setters for string, wstring, nsid, domstring, utf8string,
77     * cstring and astring get const.
78     */
79    if (!getter &&
80        (IDL_NODE_TYPE(ATTR_TYPE_DECL(attr_tree)) == IDLN_TYPE_STRING ||
81         IDL_NODE_TYPE(ATTR_TYPE_DECL(attr_tree)) == IDLN_TYPE_WIDE_STRING ||
82         IDL_tree_property_get(ATTR_TYPE_DECL(attr_tree), "nsid") ||
83         IDL_tree_property_get(ATTR_TYPE_DECL(attr_tree), "domstring")  ||
84         IDL_tree_property_get(ATTR_TYPE_DECL(attr_tree), "utf8string") ||
85         IDL_tree_property_get(ATTR_TYPE_DECL(attr_tree), "cstring")    ||
86         IDL_tree_property_get(ATTR_TYPE_DECL(attr_tree), "astring")))
87    {
88        fputs("const ", outfile);
89    }
90
91    fprintf(outfile, "%s",
92            (getter && !DIPPER_TYPE(ATTR_TYPE_DECL(attr_tree)))? "out " : "");
93    fprintf(outfile, "a%c%s", toupper(attrname[0]), attrname + 1);
94    if (!interface_write_type(ATTR_TYPE_DECL(attr_tree), getter, FALSE, FALSE, FALSE, NULL, outfile))
95        return FALSE;
96    fputc(')', outfile);
97    return TRUE;
98}
99
100static gboolean
101attr_dcl(TreeState *state)
102{
103    GSList *doc_comments;
104
105    if (!verify_attribute_declaration(state->tree))
106        return FALSE;
107
108    doc_comments =
109        IDL_IDENT(IDL_LIST(IDL_ATTR_DCL
110                           (state->tree).simple_declarations).data).comments;
111
112    if (doc_comments != NULL && comment_level >= 2) {
113        write_indent(state->file);
114        printlist(state->file, doc_comments);
115    }
116
117    /*
118     * XXX lists of attributes with the same type, e.g.
119     * attribute string foo, bar sil;
120     * are legal IDL... but we don't do anything with 'em.
121     */
122    if (IDL_LIST(IDL_ATTR_DCL(state->tree).simple_declarations).next != NULL) {
123        XPIDL_WARNING((state->tree, IDL_WARNING1,
124                       "multiple attributes in a single declaration aren't "
125                       "currently supported by xpidl"));
126    }
127
128    xpidl_write_comment(state, 2);
129
130    write_indent(state->file);
131    write_indent(state->file);
132    if (!write_attr_accessor(state->tree, state->file, TRUE, NULL))
133        return FALSE;
134    fputs(": Longword; stdcall;\n", state->file);
135
136    if (!IDL_ATTR_DCL(state->tree).f_readonly) {
137        write_indent(state->file);
138        write_indent(state->file);
139        if (!write_attr_accessor(state->tree, state->file, FALSE, NULL))
140            return FALSE;
141        fputs(": Longword; stdcall;\n", state->file);
142    }
143    /*fputc('\n', state->file);*/
144
145    return TRUE;
146}
147
148/*
149 * Shared between the interface class declaration and the NS_DECL_IFOO macro
150 * provided to aid declaration of implementation classes. 
151 * mode...
152 */
153static gboolean
154write_method_signature(IDL_tree method_tree, FILE *outfile, const char *className)
155{
156    struct _IDL_OP_DCL *op = &IDL_OP_DCL(method_tree);
157    gboolean no_generated_args = TRUE;
158    gboolean op_notxpcom =
159        (IDL_tree_property_get(op->ident, "notxpcom") != NULL);
160    const char *name;
161    IDL_tree iter;
162
163    if (op_notxpcom && !op->op_type_spec)
164        fputs("procedure ", outfile);
165    else
166        fputs("function ", outfile);
167
168    name = IDL_IDENT(op->ident).str;
169    if( is_reserved(name) )
170        fputc('_', outfile);
171    fprintf(outfile, "%c%s(", toupper(*name), name + 1);
172
173    for (iter = op->parameter_dcls; iter; iter = IDL_LIST(iter).next) {
174        if (!write_param(IDL_LIST(iter).data, outfile))
175            return FALSE;
176        if ((IDL_LIST(iter).next ||
177             (!op_notxpcom && op->op_type_spec) || op->f_varargs))
178            fputs("; ", outfile);
179        no_generated_args = FALSE;
180    }
181
182    /* make IDL return value into trailing out argument */
183    if (op->op_type_spec && !op_notxpcom) {
184        IDL_tree fake_param = IDL_param_dcl_new(IDL_PARAM_OUT,
185                                                op->op_type_spec,
186                                                IDL_ident_new("_retval"));
187        if (!fake_param)
188            return FALSE;
189        if (!write_param(fake_param, outfile))
190            return FALSE;
191        if (op->f_varargs)
192            fputs("; ", outfile);
193        no_generated_args = FALSE;
194    }
195
196    /* varargs go last */
197    if (op->f_varargs) {
198        fputs("_varargs : PVarArgs", outfile);
199        no_generated_args = FALSE;
200    }
201
202    fputc(')', outfile);
203
204    if (op_notxpcom) {
205        if (!interface_write_type(op->op_type_spec, FALSE, FALSE, FALSE, FALSE, NULL, outfile))
206            return FALSE;
207    } else {
208        fputs(": nsresult", outfile);
209    }
210    fputs("; stdcall", outfile);
211
212    return TRUE;
213}
214
215static gboolean
216codefrag(TreeState *state)
217{
218    const char *desc = IDL_CODEFRAG(state->tree).desc;
219    GSList *lines = IDL_CODEFRAG(state->tree).lines;
220    guint fragment_length;
221   
222    if (strcmp(desc, "PASCAL") && /* libIDL bug? */ strcmp(desc, "PASCAL\r") &&
223        strcmp(desc, "PASCAL_INTERFACE") && strcmp(desc, "PASCAL_INTERFACE\r") &&
224        strcmp(desc, "PASCAL_INTERFACE_STDCALL") && strcmp(desc, "PASCAL_INTERFACE_STDCALL\r")) {
225        XPIDL_WARNING((state->tree, IDL_WARNING1,
226                       "ignoring '%%{%s' escape. "
227                       "(Use '%%{PASCAL' to escape verbatim PASCAL code.)", desc));
228
229        return TRUE;
230    }
231
232    /*
233     * Emit #file directive to point debuggers back to the original .idl file
234     * for the duration of the code fragment.  We look at internal IDL node
235     * properties _file, _line to do this; hopefully they won't change.
236     *
237     * _line seems to refer to the line immediately after the closing %}, so
238     * we backtrack to get the proper line for the beginning of the block.
239     */
240    /*
241     * Looks like getting this right means maintaining an accurate line
242     * count of everything generated, so we can set the file back to the
243     * correct line in the generated file afterwards.  Skipping for now...
244     */
245
246    fragment_length = g_slist_length(lines);
247/*      fprintf(state->file, "#line %d \"%s\"\n", */
248/*              state->tree->_line - fragment_length - 1, */
249/*              state->tree->_file); */
250
251    g_slist_foreach(lines, write_codefrag_line, (gpointer)state);
252
253    return TRUE;
254}
255
256backend *
257xpidl_stdcall_dispatch(void)
258{
259    static backend result;
260    static nodeHandler table[IDLN_LAST];
261    static gboolean initialized = FALSE;
262   
263    result.emit_prolog = pascal_prolog;
264    result.emit_epilog = pascal_epilog;
265
266    write_method_signature_func = write_method_signature;
267
268    if (!initialized) {
269        table[IDLN_LIST] = pascal_list;
270        table[IDLN_ATTR_DCL] = attr_dcl;
271        table[IDLN_OP_DCL] = op_dcl;
272        table[IDLN_TYPE_ENUM] = do_enum;
273        table[IDLN_INTERFACE] = interface_interface;
274        table[IDLN_CODEFRAG] = codefrag;
275        table[IDLN_NATIVE] = check_native;
276        initialized = TRUE;
277    }
278
279    result.dispatch_table = table;
280    return &result;
281}
Note: See TracBrowser for help on using the browser.