Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / tools / perl-5.8.0 / lib / site_perl / 5.8.0 / sun4-solaris / Tk / pTk.pod
CommitLineData
86530b38
AT
1=head1 NAME
2
3Tk2portableTk - how to make your B<Tk> source portable to other
4interpreted languages.
5
6=for category C Programming
7
8=head1 Author
9
10Ilya Zakharevich <ilya@math.ohio-state.edu> has contributed most of
11this document. Many thanks.
12
13=head1 DESCRIPTION
14
15B<PortableTk> is an attempt to make B<Tk> useful from other
16languages. Currently tk4.0 runs under Perl using this
17approach. Below, I<Lang> is the notation for an external language to
18which B<PortableTk> glues B<Tk> code.
19
20The main problem with using the code developed for B<TCL> with
21different languages is the absence of data types: almost anything is
22C<char*>. It makes automatic translation hopeless. However, if you
23C<typedef> several new symbols to be C<char*>, you can still use your
24code in B<TCL>, I<and> it will make the automatic translation
25possible.
26
27Another problem with the approach that "everything is a string" is
28impossibility to have a result that says "NotApplicable" without
29setting an error. Thus different B<Tk> command return different string
30values that mean "error happened", like C<"">, C<" "> or
31C<"??">. Other languages can be more flexible, so in B<portableTk> you
32should inform the compiler that what you want to return means "error"
33(see L<Setting variables>).
34
35Currently B<PortableTk> uses several different approachs
36to simplify translation: several B<TCL> functions that are especially
37dangerous to use are undefined, so you can easily find places that
38need to be updated to use Language-independent functions based on
39compiler warnings. Eventually a way to use these Language-independent
40functions under proper B<TCL> will be also provided. The end of this
41document provides a starting point for such a project.
42
43=head1 Structure of B<pTk>, porting your code
44
45B<pTk>, that is a port of B<Tk>, is very special with respect to porting
46of other code to B<portableTk>. The problem is that currently there is
47very little hope to merge the modifications back into B<Tk>, so a
48special strategy is needed to maintain this port. Do not use this
49strategy to port your own code.
50
51B<pTk> is produced from B<Tk> via a two-step process: first, some
52manual editing (the result is in the subdirectory C<mTk>), and second,
53automatic conversion by the C<munge> script (written in Perl). Thus the
54subdirectory C<pTk/mTk> contains code with minimal possible difference
55from the virgin B<Tk> code, so it is easier to merge(1) the
56differences between B<Tk> versions into modified code.
57
58It looks like the strategy for a portable code should be exactly
59opposite: starting from B<TCL>-based code, apply C<munge>, and then
60hand-edit the resulting code. Probably it is also possible to target
61your code to B<portableTk> from scratch, since this will make it
62possible to run it under a lot of I<Lang>uages.
63
64The only reason anyone would like to look into contents of C<pTk/mTk>
65directory is to find out which constructs are not supported by
66C<munge>. On the other hand, C<pTk> directory contains code that is
67conformant to B<portableTk>, so you can look there to find example code.
68
69C<munge> is the script that converts most common B<Tk> constructs to
70their C<portableTk> equivalent. For your code to qualify, you should
71follow B<Tk> conventions on indentation and names of variables, in
72particular, the array of arguments for the C<...CmdProc> should be
73called C<argv>.
74
75For details on what C<munge> can do, see
76L<Translation of some TCL functions>.
77
78=head1 B<PortableTk> API
79
80=head2 Checking what you are running under
81
82B<PortableTk> provides a symbol C<????>. If this symbol is defined,
83your source is compiled with it.
84
85=head2 New types of configuration options
86
87B<PortableTk> defines several new types of configuration options:
88
89 TK_CONFIG_CALLBACK
90 TK_CONFIG_LANGARG
91 TK_CONFIG_SCALARVAR
92 TK_CONFIG_HASHVAR
93 TK_CONFIG_ARRAYVAR
94 TK_CONFIG_IMAGE
95
96You should use them instead of TK_CONFIG_STRING whenever
97appropriate. This allows your application to receive a direct
98representation of the corresponding resource instead of the string
99representation, if this is possible under given language.
100
101???? It looks like C<TK_CONFIG_IMAGE> and C<TK_CONFIG_SCALARVAR> set
102variables of type C<char*>.
103
104=head2 Language data
105
106The following data types are defined:
107
108=over 4
109
110=item C<Arg>
111
112is the main datatype of the language. This is a type that your C
113function gets pointers to for arguments when the corresponding I<Lang>
114function is called. The corresponding config type is
115C<TK_CONFIG_LANGARG>.
116
117This is also a type that keeps information about contents of I<Lang>
118variable.
119
120=item C<Var>
121
122Is a substitute for a C<char *> that contains name of variable. In
123I<Lang> it is an object that contains reference to another I<Lang>
124variable.
125
126=item C<LangResultSave>
127
128????
129
130=item C<LangCallback>
131
132C<LangCallback*> a substitute for a C<char *> that contains command to
133call. The corresponding config type is C<TK_CONFIG_CALLBACK>.
134
135=item C<LangFreeProc>
136
137It is the type that the C<Lang_SplitList> sets. Before you call it,
138declare
139
140 Args *args;
141 LangFreeProc *freeProc = NULL;
142 ...
143 code = Lang_SplitList(interp, value,
144 &argc, &args, &freeProc);
145
146After you use the split values, call
147
148 if (args != NULL && freeProc) (*freeProc)(argc,args);
149
150It is not guaranteed that the C<args> can survive deletion of C<value>.
151
152=back
153
154=head2 Conversion
155
156The following macros and functions are used for conversion between
157strings and the additional types:
158
159 LangCallback * LangMakeCallback(Arg)
160 Arg LangCallbackArg(LangCallback *)
161 char * LangString(Arg)
162
163After you use the result of LangCallbackArg(), you should free it with
164C<freeProc> C<LANG_DYNAMIC> (it is not guaranteed that any change of
165C<Arg> will not be reflected in <LangCallback>, so you cannot do
166LangSet...() in between, and you should reset it to C<NULL> if you
167want to do any further assignments to this C<Arg>).
168
169The following function returns the C<Arg> that is a reference to C<Var>:
170
171 Arg LangVarArg(Var)
172
173???? It is very anti-intuitive, I hope the name is changed.
174
175 int LangCmpCallback(LangCallback *a,Arg b)
176
177(currently only a stub), and, at last,
178
179 LangCallback * LangCopyCallback(LangCallback *)
180
181=head2 Callbacks
182
183Above we have seen the new datatype C<LangCallback> and the
184corresponding I<Config option> C<TK_CONFIG_CALLBACK>. The following
185functions are provided for manipulation of C<LangCallback>s:
186
187 void LangFreeCallback(LangCallback *)
188 int LangDoCallback(Tcl_Interp *,LangCallback *,
189 int result,int argc, char *format,...)
190
191The argument C<format> of C<LangDoCallback> should contain a string that is
192suitable for C<sprintf> with optional arguments of C<LangDoCallback>.
193C<result> should be false if result of callback is not needed.
194
195 int LangMethodCall(Tcl_Interp *,Arg,char *method,
196 int result,int argc,...)
197
198????
199
200Conceptually, C<LangCallback*> is a substitute for ubiquitous C<char *>
201in B<TCL>. So you should use C<LangFreeCallback> instead of C<ckfree>
202or C<free> if appropriate.
203
204=head2 Setting variables
205
206 void LangFreeArg (Arg, Tcl_FreeProc *freeProc)
207 Arg LangCopyArg (Arg);
208 void Tcl_AppendArg (Tcl_Interp *interp, Arg)
209 void LangSetString(Arg *, char *s)
210 void LangSetDefault(Arg *, char *s)
211
212These two are equivalent unless s is an empty string. In this case
213C<LangSetDefault> behaves like C<LangSetString> with C<s==NULL>, i.e.,
214it sets the current value of the I<Lang> variable to be false.
215
216 void LangSetInt(Arg *,int)
217 void LangSetDouble(Arg *,double)
218
219The I<Lang> functions separate uninitialized and initialized data
220comparing data with C<NULL>. So the declaration for an C<Arg> should
221look like
222
223 Arg arg = NULL;
224
225if you want to use this C<arg> with the above functions. After you are
226done, you should use C<LangFreeArg> with C<TCL_DYNAMIC> as C<freeProc>.
227
228=head2 Language functions
229
230Use
231
232=over 4
233
234=item C<int LangNull(Arg)>
235
236to check that an object is false;
237
238=item C<int LangStringMatch(char *string, Arg match)>
239
240????
241
242=item C<void LangExit(int)>
243
244to make a proper shutdown;
245
246=item C<int LangEval(Tcl_Interp *interp, char *cmd, int global)>
247
248to call I<Lang> C<eval>;
249
250=item C<void Lang_SetErrorCode(Tcl_Interp *interp,char *code)>
251
252=item C<char *Lang_GetErrorCode(Tcl_Interp *interp)>
253
254=item C<char *Lang_GetErrorInfo(Tcl_Interp *interp)>
255
256=item C<void LangCloseHandler(Tcl_Interp *interp,Arg arg,FILE *f,Lang_FileCloseProc *proc)>
257
258currently stubs only;
259
260=item C<int LangSaveVar(Tcl_Interp *,Arg arg,Var *varPtr,int type)>
261
262to save the structure C<arg> into I<Lang> variable C<*varPtr>;
263
264=item C<void LangFreeVar(Var var)>
265
266to free the result;
267
268=item C<int LangEventCallback(Tcl_Interp *,LangCallback *,XEvent *,KeySym)>
269
270????
271
272=item C<int LangEventHook(int flags)>
273
274=item C<void LangBadFile(int fd)>
275
276=item C<int LangCmpConfig(char *spec, char *arg, size_t length)>
277
278unsupported????;
279
280=item C<void Tcl_AppendArg (Tcl_Interp *interp, Arg)>
281
282=back
283
284Another useful construction is
285
286 Arg variable = LangFindVar(interp, Tk_Window tkwin, char *name);
287
288After using the above function, you should call
289
290 LangFreeVar(Var variable);
291
292???? Note discrepancy in types!
293
294If you want to find the value of a variable (of type C<Arg>) given the
295variable name, use C<Tcl_GetVar(interp, varName, flags)>. If you are
296interested in the string value of this variable, use
297C<LangString(Tcl_GetVar(...))>.
298
299To get a B<C> array of C<Arg> of length C<n>, use
300
301 Arg *args = LangAllocVec(n);
302 ...
303 LangFreeVec(n,args);
304
305You can set the values of the C<Arg>s using C<LangSet...> functions,
306and get string value using C<LangString>.
307
308If you want to merge an array of C<Arg>s into one C<Arg> (that will
309be an array variable), use
310
311 result = Tcl_Merge(listLength, list);
312
313=head2 Translation of some TCL functions
314
315We mark items that can be dealt with by C<munge> by I<Autoconverted>.
316
317=over 4
318
319=item C<Tcl_AppendResult>
320
321does not take C<(char*)NULL>, but C<NULL> as delimiter. I<Autoconverted>.
322
323=item C<Tcl_CreateCommand>, C<Tcl_DeleteCommand>
324
325C<Tk_CreateWidget>, C<Tk_DeleteWidget>, the second argument is the
326window itself, not the pathname. I<Autoconverted>.
327
328=item C<sprintf(interp-E<gt>result, "%d %d %d %d",...)>
329
330C<Tcl_IntResults(interp,4,0,...)>. I<Autoconverted>.
331
332=item C<interp-E<gt>result = "1";>
333
334C<Tcl_SetResult(interp,"1", TCL_STATIC)>. I<Autoconverted>.
335
336=item Reading C<interp-E<gt>result>
337
338C<Tcl_GetResult(interp)>. I<Autoconverted>.
339
340=item C<interp-E<gt>result = Tk_PathName(textPtr-E<gt>tkwin);>
341
342C<Tk_WidgetResult(interp,textPtr-E<gt>tkwin)>. I<Autoconverted>.
343
344=item Sequence C<Tcl_PrintDouble, Tcl_PrintDouble, ..., Tcl_AppendResult>
345
346Use a single command
347
348 void Tcl_DoubleResults(Tcl_Interp *interp, int append,
349 int argc,...);
350
351C<append> governs whether it is required to clear the result first.
352
353A similar command for C<int> arguments is C<Tcl_IntResults>.
354
355=item C<Tcl_SplitList>
356
357Use C<Lang_SplitList> (see the description above).
358
359=back
360
361=head1 Translation back to TCL
362
363To use your B<portableTk> program with B<TCL>, put
364
365 #include "ptcl.h"
366
367I<before> inclusion of C<tk.h>, and link the resulting code with
368C<ptclGlue.c>.
369
370These files currently implement the following:
371
372=over 4
373
374=item Additional config types:
375
376 TK_CONFIG_CALLBACK
377 TK_CONFIG_LANGARG
378 TK_CONFIG_SCALARVAR
379 TK_CONFIG_HASHVAR
380 TK_CONFIG_ARRAYVAR
381 TK_CONFIG_IMAGE
382
383=item Types:
384
385 Var, Arg, LangCallback, LangFreeProc.
386
387=item Functions and macros:
388
389 Lang_SplitList, LangString, LangSetString, LangSetDefault,
390 LangSetInt, LangSetDouble Tcl_ArgResult, LangCallbackArg,
391 LangSaveVar, LangFreeVar,
392 LangFreeSplitProc, LangFreeArg, Tcl_DoubleResults, Tcl_IntResults,
393 LangDoCallback, Tk_WidgetResult, Tcl_CreateCommand,
394 Tcl_DeleteCommand, Tcl_GetResult.
395
396=back
397
398Current implementation contains enough to make it possible to compile
399C<mTk/tkText*.[ch]> with the virgin B<Tk>.
400
401=head2 New types of events ????
402
403PortableTk defines following new types of events:
404
405 TK_EVENTTYPE_NONE
406 TK_EVENTTYPE_STRING
407 TK_EVENTTYPE_NUMBER
408 TK_EVENTTYPE_WINDOW
409 TK_EVENTTYPE_ATOM
410 TK_EVENTTYPE_DISPLAY
411 TK_EVENTTYPE_DATA
412
413and a function
414
415 char * Tk_EventInfo(int letter,
416 Tk_Window tkwin, XEvent *eventPtr,
417 KeySym keySym, int *numPtr, int *isNum, int *type,
418 int num_size, char *numStorage)
419
420=head1 Checking for trouble
421
422If you start with working TCL code, you can start convertion using
423the above hints. Good indication that you are doing is OK is absence
424of C<sprintf> and C<sscanf> in your code (at least in the part that is
425working with interpreter).
426
427=head1 Additional API
428
429What is described here is not included into base B<portableTk>
430distribution. Currently it is coded in B<TCL> and as Perl macros (core
431is coded as functions, so theoretically you can use the same object
432files with different interpreted languages).
433
434=head2 C<ListFactory>
435
436Dynamic arrays in B<TCL> are used for two different purposes: to
437construct strings, and to construct lists. These two usages will have
438separate interfaces in other languages (since list is a different type
439from a string), so you should use a different interface in your code.
440
441The type for construction of dynamic lists is C<ListFactory>. The API
442below is a counterpart of the API for construction of dynamic lists
443in B<TCL>:
444
445 void ListFactoryInit(ListFactory *)
446 void ListFactoryFinish(ListFactory *)
447 void ListFactoryFree(ListFactory *)
448 Arg * ListFactoryArg(ListFactory *)
449 void ListFactoryAppend(ListFactory *, Arg *arg)
450 void ListFactoryAppendCopy(ListFactory *, Arg *arg)
451 ListFactory * ListFactoryNewLevel(ListFactory *)
452 ListFactory * ListFactoryEndLevel(ListFactory *)
453 void ListFactoryResult(Tcl_Interp *, ListFactory *)
454
455The difference is that a call to C<ListFactoryFinish> should precede the
456actual usage of the value of C<ListFactory>, and there are two
457different ways to append an C<Arg> to a C<ListFactory>:
458ListFactoryAppendCopy() guarantees that the value of C<arg> is copied
459to the list, but ListFactoryAppend() may append to the list a
460reference to the current value of C<arg>. If you are not going to change
461the value of C<arg> after appending, the call to ListFactoryAppend may
462be quicker.
463
464As in B<TCL>, the call to ListFactoryFree() does not free the
465C<ListFactory>, only the objects it references.
466
467The functions ListFactoryNewLevel() and ListFactoryEndLevel() return a
468pointer to a C<ListFactory> to fill. The argument of
469ListFactoryEndLevel() cannot be used after a call to this function.
470
471=head2 DStrings
472
473Production of strings are still supported in B<portableTk>.
474
475=head2 Accessing C<Arg>s
476
477The following functions for getting a value of an C<Arg> I<may> be
478provided:
479
480 double LangDouble(Arg)
481 int LangInt(Arg)
482 long LangLong(Arg)
483 int LangIsList(Arg arg)
484
485The function LangIsList() is supported only partially under B<TCL>,
486since there is no data types. It checks whether there is a space
487inside the string C<arg>.
488
489=head2 Assigning numbers to C<Arg>s
490
491While LangSetDouble() and LangSetInt() are supported ways to assign
492numbers to assign an integer value to a variable, for the sake of
493efficiency under B<TCL> it is supposed that the destination of these
494commands was massaged before the call so it contains a long enough
495string to sprintf() the numbers inside it. If you are going to
496immediately use the resulting C<Arg>, the best way to do this is to
497declare a buffer in the beginning of a block by
498
499 dArgBuffer;
500
501and assign this buffer to the C<Arg> by
502
503 void LangSetDefaultBuffer(Arg *)
504
505You can also create the buffer(s) manually and assign them using
506
507 void LangSetBuffer(Arg *, char *)
508
509This is the only choice if you need to assign numeric values to
510several C<Arg>s simultaneously. The advantage of the first approach is
511that the above declarations can be made C<nop>s in different languages.
512
513Note that if you apply C<LangSetDefaultBuffer> to an C<Arg> that
514contains some value, you can create a leak if you do not free that
515C<Arg> first. This is a non-problem in real languages, but can be a
516trouble in C<TCL>, unless you use only the above API.
517
518=head2 Creating new C<Arg>s
519
520The API for creating a new C<Arg> is
521
522 void LangNewArg(Arg *, LangFreeProc *)
523
524The API for creating a new C<Arg> is absent. Just initialize C<Arg> to
525be C<NULL>, and apply one of C<LangSet...> methods.
526
527After you use this C<Arg>, it should be freed thusly:
528
529C<LangFreeArg(arg, freeProc)>.
530
531=head2 Evaluating a list
532
533Use
534
535 int LangArgEval(Tcl_Interp *, Arg arg)
536
537Here C<arg> should be a list to evaluate, in particular, the first
538element should be a C<LangCallback> massaged to be an C<Arg>. The
539arguments can be send to the subroutine by reference or by value in
540different languages.
541
542=head2 Getting result as C<Arg>
543
544Use C<Tcl_ArgResult>. It is not guaranteed that result survives this
545operation, so the C<Arg> you get should be the only mean to access the
546data from this moment on. After you use this C<Arg>, you should free
547it with C<freeProc> C<LANG_DYNAMIC> (you can do LangSet...() in between).
548
549=cut
550