root/lang/pascal/xpidlpas/xpidlpas_const.c

Revision 4249, 8.0 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
46#define AS_DECL 0
47#define AS_CALL 1
48#define AS_IMPL 2
49
50static gboolean write_method_signature(IDL_tree method_tree, FILE *outfile,
51                                       int mode, const char *className);
52static gboolean write_attr_accessor(IDL_tree attr_tree, FILE * outfile,
53                                    gboolean getter,
54                                    int mode, const char *className);
55
56static void
57write_classname_iid_define(FILE *file, const char *className)
58{
59    const char *iidName;
60    if (className[0] == 'n' && className[1] == 's') {
61        /* backcompat naming styles */
62        fputs("NS_", file);
63        iidName = className + 2;
64    } else {
65        iidName = className;
66    }
67    while (*iidName)
68        fputc(toupper(*iidName++), file);
69    fputs("_IID", file);
70}
71
72static void
73write_classname_const_define(FILE *file, const char *className)
74{
75    const char *iidName;
76    if (className[0] == 'n' && className[1] == 's') {
77        /* backcompat naming styles */
78        fputs("NS_", file);
79        iidName = className + 2;
80    } else {
81        iidName = className;
82    }
83    while (*iidName)
84        fputc(toupper(*iidName++), file);
85}
86
87static gboolean
88interface(TreeState *state)
89{
90    IDL_tree iface = state->tree, iter, orig;
91    char *className = IDL_IDENT(IDL_INTERFACE(iface).ident).str;
92    gboolean ok = TRUE;
93    const char *iid;
94    struct nsID id;
95    char iid_parsed[UUID_LENGTH];
96    GSList *doc_comments = IDL_IDENT(IDL_INTERFACE(iface).ident).comments;
97
98    if (!verify_interface_declaration(iface))
99        return FALSE;
100
101#define FAIL    do {ok = FALSE; goto out;} while(0)
102
103    iid = IDL_tree_property_get(IDL_INTERFACE(iface).ident, "uuid");
104    if (iid) {
105        /* Redundant, but a better error than 'cannot parse.' */
106        if (strlen(iid) != 36) {
107            IDL_tree_error(state->tree, "IID %s is the wrong length\n", iid);
108            FAIL;
109        }
110
111        /*
112         * Parse uuid and then output resulting nsID to string, to validate
113         * uuid and normalize resulting .h files.
114         */
115        if (!xpidl_parse_iid(&id, iid)) {
116            IDL_tree_error(state->tree, "cannot parse IID %s\n", iid);
117            FAIL;
118        }
119        if (!xpidl_sprint_iid(&id, iid_parsed)) {
120            IDL_tree_error(state->tree, "error formatting IID %s\n", iid);
121            FAIL;
122        }
123
124        /* NS_ISUPPORTS_IID: TGUID = '{00000000-0000-0000-c000-000000000046}'; */
125        /*fputs("#define ", state->file);*/
126        write_indent(state->file);
127        write_classname_iid_define(state->file, className);
128        fprintf(state->file, ": TGUID = \'{%s}\';", iid_parsed);
129        fputc('\n', state->file);
130    } else {
131        IDL_tree_error(state->tree, "interface %s lacks a uuid attribute\n",
132            className);
133        FAIL;
134    }
135
136    orig = state->tree; /* It would be nice to remove this state-twiddling. */
137
138    state->tree = IDL_INTERFACE(iface).body;
139
140    if (state->tree && !xpidl_process_node(state))
141        FAIL;
142
143    fputc('\n', state->file);
144   
145#undef FAIL
146
147out:
148    return ok;
149}
150
151static gboolean
152do_const_dcl(TreeState *state)
153{
154    IDL_tree parent = IDL_get_parent_node(state->tree, IDLN_INTERFACE, NULL);
155    /*IDL_tree parent = state->tree->up;*/
156    char *className = IDL_IDENT(IDL_INTERFACE(parent).ident).str;
157    gboolean ok = FALSE;
158    struct _IDL_CONST_DCL *dcl = &IDL_CONST_DCL(state->tree);
159    const char *name = IDL_IDENT(dcl->ident).str;
160    gboolean is_signed;
161    GSList *doc_comments = IDL_IDENT(dcl->ident).comments;
162    IDL_tree real_type;
163    const char *const_format;
164
165    if (!verify_const_declaration(state->tree))
166        goto FAIL;
167
168    if (doc_comments != NULL && comment_level >= 2) {
169        write_indent(state->file);
170        printlist(state->file, doc_comments);
171    }
172
173    /* Could be a typedef; try to map it to the real type. */
174    real_type = find_underlying_type(dcl->const_type);
175    real_type = real_type ? real_type : dcl->const_type;
176    is_signed = IDL_TYPE_INTEGER(real_type).f_signed;
177
178    const_format = is_signed ? "%" IDL_LL "d" : "%" IDL_LL "u";
179    write_indent(state->file);
180    write_classname_const_define(state->file, className);
181    fprintf(state->file, "_%s = ", name);
182    fprintf(state->file, const_format, IDL_INTEGER(dcl->const_exp).value);
183    fprintf(state->file, ";\n");
184
185    ok = TRUE;
186FAIL:;
187    return ok;
188}
189
190static gboolean
191codefrag(TreeState *state)
192{
193    const char *desc = IDL_CODEFRAG(state->tree).desc;
194    GSList *lines = IDL_CODEFRAG(state->tree).lines;
195    guint fragment_length;
196   
197    if (strcmp(desc, "PASCAL") && /* libIDL bug? */ strcmp(desc, "PASCAL\r")) {
198        XPIDL_WARNING((state->tree, IDL_WARNING1,
199                       "ignoring '%%{%s' escape. "
200                       "(Use '%%{PASCAL' to escape verbatim PASCAL code.)", desc));
201
202        return TRUE;
203    }
204
205    /*
206     * Emit #file directive to point debuggers back to the original .idl file
207     * for the duration of the code fragment.  We look at internal IDL node
208     * properties _file, _line to do this; hopefully they won't change.
209     *
210     * _line seems to refer to the line immediately after the closing %}, so
211     * we backtrack to get the proper line for the beginning of the block.
212     */
213    /*
214     * Looks like getting this right means maintaining an accurate line
215     * count of everything generated, so we can set the file back to the
216     * correct line in the generated file afterwards.  Skipping for now...
217     */
218
219    fragment_length = g_slist_length(lines);
220/*      fprintf(state->file, "#line %d \"%s\"\n", */
221/*              state->tree->_line - fragment_length - 1, */
222/*              state->tree->_file); */
223
224    g_slist_foreach(lines, write_codefrag_line, (gpointer)state);
225
226    return TRUE;
227}
228
229backend *
230xpidl_const_dispatch(void)
231{
232    static backend result;
233    static nodeHandler table[IDLN_LAST];
234    static gboolean initialized = FALSE;
235   
236    result.emit_prolog = pascal_prolog;
237    result.emit_epilog = pascal_epilog;
238
239    if (!initialized) {
240        table[IDLN_LIST] = pascal_list;
241        table[IDLN_INTERFACE] = interface;
242        table[IDLN_CODEFRAG] = codefrag;
243        table[IDLN_CONST_DCL] = do_const_dcl;
244        table[IDLN_NATIVE] = check_native;
245        initialized = TRUE;
246    }
247
248    result.dispatch_table = table;
249    return &result;
250}
Note: See TracBrowser for help on using the browser.