1%{
2/*
3 * Copyright 2004, 2008 by the Massachusetts Institute of Technology.
4 * All Rights Reserved.
5 *
6 * Export of this software from the United States of America may
7 *   require a specific license from the United States Government.
8 *   It is the responsibility of any person or organization contemplating
9 *   export to obtain such a license before exporting.
10 * 
11 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
12 * distribute this software and its documentation for any purpose and
13 * without fee is hereby granted, provided that the above copyright
14 * notice appear in all copies and that both that copyright notice and
15 * this permission notice appear in supporting documentation, and that
16 * the name of M.I.T. not be used in advertising or publicity pertaining
17 * to distribution of the software without specific, written prior
18 * permission.  Furthermore if you modify this software you must label
19 * your software as modified software and not distribute it in such a
20 * fashion that it might be confused with the original M.I.T. software.
21 * M.I.T. makes no representations about the suitability of
22 * this software for any purpose.  It is provided "as is" without express
23 * or implied warranty.
24 *
25 *
26 * Input for wrapper generator program SWIG for profile routines.
27 */
28#include <errno.h>
29#include "com_err.h"
30#include "profile.h"
31
32#ifdef SWIGTCL
33/* Reduce warnings about cast discarding const to just this one, from
34   every SWIG-generated call to Tcl_SetResult.  */
35static void my_tcl_setresult(Tcl_Interp *i, const char *str, Tcl_FreeProc *f)
36{
37    Tcl_SetResult(i, (char *) str, f);
38}
39#undef Tcl_SetResult
40#define Tcl_SetResult my_tcl_setresult
41#endif
42%}
43
44%include "typemaps.i"
45
46/* These should perhaps be part of the general SWIG package, maybe?  */
47%typemap(in,numinputs=0) SWIGTYPE *OUTPUT ($1_basetype tmp) {
48    /*generic swigtype hack*/ $1 = &tmp;
49}
50%typemap(tcl8,argout) SWIGTYPE *OUTPUT
51  "/*generic swigtype hack*/ Tcl_SetObjResult(interp,SWIG_NewInstanceObj((void *) *$1, $*1_descriptor,0));";
52%typemap(python,argout) SWIGTYPE *OUTPUT
53  "/*generic swigtype hack*/ resultobj = SWIG_NewPointerObj((void *) *$1, $*1_descriptor,0);";
54
55%module profile
56
57typedef long errcode_t;
58%inline %{
59typedef void **iter_t; /* ick */
60%}
61
62/* As a hack, if we have too much trouble trying to manage output
63   arguments for functions returning error codes, this output argument
64   type will let us twist it around into a function returning the
65   interesting type, and incidentally possibly raising an error.  */
66%typemap(in,numinputs=0) errcode_t * (errcode_t tmp) {
67    /* in errcode_t * */
68    tmp = 0;
69    $1 = &tmp;
70}
71%typemap(tcl8,argout) errcode_t* {
72    /* argout errcode_t * */
73    if (*$1) {
74	/* There could be a memory leak here in the SWIG-Tcl layer,
75	   I'm not sure.  Not going to worry about it though.  */
76	Tcl_SetResult(interp, (char *) error_message(*$1), TCL_STATIC);
77	SWIG_fail;
78    }
79}
80/* returning errcode_t */
81%typemap(tcl8,out) errcode_t {
82    /* out errcode_t $1 */
83    if ($1) {
84	/* There could be a memory leak here in the SWIG-Tcl layer,
85	   I'm not sure.  Not going to worry about it though.  */
86	Tcl_SetResult(interp, (char *) error_message($1), TCL_STATIC);
87	SWIG_fail;
88    }
89}
90%typemap(python,argout) errcode_t* {
91    /* do something with *($1) */ abort();
92}
93%typemap(python,out) errcode_t {
94    /* do something with $1 */ abort();
95}
96
97/* "char **OUTPUT" : Supply a place for the function to stuff one
98   string pointer.  */
99%typemap(in,numinputs=0) char **OUTPUT (char * tmp) {
100    /* in char **OUTPUT */
101    tmp = NULL;
102    $1 = &tmp;
103}
104%typemap(tcl8,argout) char **OUTPUT {
105    /* argout char **OUTPUT */
106/*    Tcl_SetResult(interp, *$1, TCL_DYNAMIC); */
107    char *s = ($1 && *$1) ? *$1 : "";
108    Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp),
109			     Tcl_NewStringObj(s, strlen(s)));
110}
111%typemap(freearg) char **OUTPUT {
112    /* There may be a memory leak here.  Investigate later, if anyone
113       cares.  */
114/*    profile_release_string(*$1); */
115}
116
117/* "char **nullterm" : Null-terminated list of strings, from a single
118   input value which is a list.  */
119%typemap(tcl8,in) char **nullterm {
120    /* in char **nullterm */
121    int n;
122    if (Tcl_SplitList(interp, Tcl_GetStringFromObj($input,NULL), &n, &$1) == TCL_ERROR) SWIG_fail;
123}
124%typemap(tcl8,freearg) char **nullterm {
125    /* freearg char **nullterm */
126    if ($1) { Tcl_Free((char *)$1); $1 = (char **) NULL; }
127}
128
129/* "char ***OUTPUT" : Supply a place for the function to stuff a
130   pointer to a list of strings, which will be combined into a list to
131   return, and the data from the function itself freed before
132   returning.  */
133%typemap(in,numinputs=0) char ***OUTPUT (char ** tmp) {
134    /* in char ***OUTPUT */
135    tmp = NULL;
136    $1 = &tmp;
137}
138%typemap(tcl8,argout) char ***OUTPUT {
139    /* argout char ***OUTPUT */
140    int i;
141    for (i = 0; (*$1)[i]; i++)
142	Tcl_AppendElement(interp, (*$1)[i]);
143}
144%typemap(tcl8,freearg) char ***OUTPUT {
145    /* freearg char ***OUTPUT */
146    profile_free_list(*$1);
147}
148
149typedef struct _profile_t *profile_t;
150
151errcode_t profile_init_path(const char *path = NULL, profile_t *OUTPUT);
152errcode_t profile_init(const char **nullterm = NULL, profile_t *OUTPUT);
153errcode_t profile_flush(profile_t);
154errcode_t profile_flush_to_file(profile_t, const char *path);
155/* Nota bene: There is nothing at all in this code to prevent a script
156   from accessing a profile object after calling one of these routines
157   to destroy it!  */
158void profile_abandon(profile_t);
159void profile_release(profile_t);
160
161errcode_t profile_get_values(profile_t p, const char **nullterm,
162			     char ***OUTPUT);
163
164/* XXX Because of the way this is specified, the default can only be
165   given if you're actually using all three names (e.g., for realm
166   data).  SWIG currently doesn't support a non-optional argument (at
167   the scripting-language level -- the output-only argument doesn't
168   count) after an optional one.  */
169extern errcode_t profile_get_string(profile_t p,
170				    const char *name,
171				    const char *subname,
172				    const char *subsubname = NULL,
173				    const char *defval = NULL,
174				    char **OUTPUT);
175
176errcode_t profile_get_integer(profile_t p,
177			      const char *name,
178			      const char *subname,
179			      const char *subsubname = NULL,
180			      int defval = 0,
181			      int *OUTPUT);
182errcode_t profile_get_boolean(profile_t p,
183			      const char *name,
184			      const char *subname,
185			      const char *subsubname = NULL,
186			      int defval = 0,
187			      int *OUTPUT);
188errcode_t profile_get_relation_names(profile_t p,
189				     const char **nullterm,
190				     char ***OUTPUT);
191errcode_t profile_get_subsection_names(profile_t p,
192				       const char **nullterm,
193				       char ***OUTPUT);
194
195%rename("profile_iterator_create") iter_create;
196%rename("profile_iterator_free") iter_free;
197%inline %{
198static errcode_t iter_create(profile_t p, const char **nullterm,
199			     int flags, iter_t *OUTPUT)
200{
201    iter_t it;
202    errcode_t err;
203    char **args;
204
205    it = malloc(sizeof(*it));
206    if (it == NULL)
207	return ENOMEM;
208    {
209	/* Memory leak!
210
211	   The profile code seems to assume that I'll keep the string
212	   array around for as long as the iterator is valid; I can't
213	   create the iterator and then throw them away.
214
215	   But right now, I can't be bothered to track the necessary
216	   information to do the cleanup later.  */
217	int count, j;
218	for (count = 0; nullterm[count]; count++) ;
219	args = calloc(count+1, sizeof(char *));
220	if (args == NULL)
221	    return ENOMEM;
222	for (j = 0; j < count; j++) {
223	    args[j] = strdup(nullterm[j]);
224	    if (args[j] == NULL)
225		return ENOMEM;
226	}
227	args[j] = NULL;
228    }
229    err = profile_iterator_create(p, args, flags, it);
230    if (err)
231	free(it);
232    else
233	*OUTPUT = it;
234    return err;
235}
236static errcode_t iter_free(iter_t i)
237{
238    profile_iterator_free(i);
239    free(i);
240}
241%}
242errcode_t profile_iterator(iter_t, char **OUTPUT, char **OUTPUT);
243
244
245errcode_t profile_update_relation(profile_t p, const char **nullterm,
246				  const char *oldval,
247				  const char *newval = NULL);
248errcode_t profile_clear_relation(profile_t p, const char **nullterm);
249errcode_t profile_rename_section(profile_t p, const char **nullterm,
250				 const char *new_name = NULL);
251errcode_t profile_add_relation(profile_t p, const char **nullterm,
252			       const char *new_val = NULL);
253/* XXX Should be using profile_free_buffer blah.  */
254errcode_t profile_flush_to_buffer(profile_t p, char **OUTPUT);
255
256#ifdef SWIGTCL
257%include "tclsh.i"
258#endif
259