This file is indexed.

/usr/share/calc/help/new_custom is in apcalc-common 2.12.5.0-1build1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
Guidelines for adding custom functions
--------------------------------------

Step 0: Determine if is should it be done?

    The main focus for calc is to provide a portable platform for
    multi-precision calculations in a C-like environment.  You should
    consider implementing algorithms in the calc language as a first
    choice.  Sometimes an algorithm requires use of special hardware, a
    non-portable OS or pre-compiled C library.	In these cases a custom
    interface may be needed.

    The custom function interface is intended to make is easy for
    programmers to add functionality that would be otherwise
    un-suitable for general distribution.  Functions that are
    non-portable (machine, hardware or OS dependent) or highly
    specialized are possible candidates for custom functions.

    So before you go to step 1, ask yourself:

	+ Can I implement this as a calc resource file or calc shell script?

	    If Yes, write the shell script or resource file and be done with it.
	    If No, continue to the next question ...

	+ Does it require the use of non-portable features,
	  OS specific support or special hardware?

	    If No, write it as a regular builtin function.
	    If Yes, continue to step 1 ...


Step 1: Do some background work

    First ... read this file ALL THE WAY THROUGH before implementing
    anything in Steps 2 and beyond!

    If you are not familiar with calc internals, we recommend that
    you look at some examples of custom functions.  Look at the
    the following source files:

	custom.c
	custom.h
	custom/custtbl.c
	custom/c_*.[ch]
	custom/*.cal
	help/custom		(or run:  calc help custom)

    You would be well advised to look at a more recent calc source
    such as one available in from the calc version archive.
    See the following for more details:

	help/archive		(or run:  calc help archive)


Step 2: Name your custom function

    We suggest that you pick a name that does not conflict with
    one of the builtin names.  It makes it easier to get help
    via the help interface and avoid confusion down the road.

    You should avoid picking a name that matches a file or
    directory name under ${HELPDIR} as well.  Not all help
    files are associated with builtin function names.

    For purposes of this file, we will use the name 'curds'
    as our example custom function name.


Step 3: Document your custom function

    No this step is NOT out of order.  We recommend that you write the
    help file associated with your new custom function EARLY.  By
    experience we have found that the small amount of effort made to
    write "how the custom function will be used" into a help file pays
    off in a big way when it comes to coding.  Often the effort of
    writing a help file will clarify fuzzy aspects of your design.
    Besides, unless you write the help file first, it will likely never
    be written later on.  :-(

    OK ... we will stop preaching now ...

    [[ From now on we will give filenames relative to the custom directory ]]

    Take a look at one of the example custom help files:

	custom/devnull
	custom/argv
	custom/help
	custom/sysinfo

    You can save time by using one of the custom help files
    as a template.  Copy one of these files to your own help file:

	cd custom
	cp sysinfo curds

    and edit it accordingly.


Step 4: Write your test code

    No this step is NOT out of order either.  We recommend that you
    write a simple calc script that will call your custom function and
    check the results.

    This script will be useful while you are debugging your code.  In
    addition, if you wish to submit your code for distribution, this
    test code will be an import part of your submission.  Your test
    code will also service as additional for your custom function.

    Oops ... we said we would stop preaching, sorry about that ...

    You can use one of the following as a template:

	custom/argv.cal
	custom/halflen.cal

    Copy one of these to your own file:

	cd custom
	cp halflen.cal curds.cal

    and exit it accordingly.  In particular you will want to:

	remove our header disclaimer (or put your own on)

	change the name from halflen() to curds()

	change the comment from 'halflen - determine the length ...' to
	'curds - brief description about ...'

	change other code as needed.


Step 5: Write your custom function

    By convention, the files we ship that contain custom function
    interface code in filenames of the form:

	c_*.c

    We suggest that you use filenames of the form:

	u_*.c

    to avoid filename conflicts.

    We recommend that you use one of the c_*.c files as a template.
    Copy an appropriate file to your file:

	cd custom
	cp c_argv.c u_curds.c

    Before you edit it, you should note that there are several important
    features of this file.

	a) All of the code in the file is found between #if ... #endif:

		/*
		 * only comments and blank lines at the top
		 */

		#if defined(CUSTOM)

		... all code, #includes, #defines etc.

		#endif /* CUSTOM */

	   This allows this code to 'go away' when the upper Makefile
	   disables the custom code (because ALLOW_CUSTOM no longer
	   has the -DCUSTOM define).

	b) The function type must be:

		/*ARGSUSED*/
		VALUE
		u_curds(char *name, int count, VALUE **vals)

	   The 3 args are passed in by the custom interface
	   and have the following meaning:

		name	The name of the custom function that
			was called.  In particular, this is the first
			string arg that was given to the custom()
			builtin.  This is the equivalent of argv[0] for
			main() in C programming.

			The same code can be used for multiple custom
			functions by processing off of this value.

		count	This is the number of additional args that
			was given to the custom() builtin.  Note
			that count does NOT include the name arg.
			This is similar to argc except that count
			is one less than the main() argc interface.

			For example, a call of:

			    custom("curds", a, b, c)

			would cause count to be passed as 3.

		vals	This is a pointer to an array of VALUEs.
			This is the equivalent of argv+1 for
			main() in C programming.  The difference
			here is that vals[0] refers to the 1st
			parameter AFTER the same.

			For example, a call of:

			    custom("curds", a, b, c)

			would cause vals to point to the following array:

			    vals[0]  points to	a
			    vals[1]  points to	b
			    vals[2]  points to	c

	   NOTE: If you do not use any of the 3 function parameters,
	   then you should declare that function parameter to be UNUSED.
	   For example, if the count and vals parameters were not used
	   in your custom function, then your declaraction should be:

		/*ARGSUSED*/
		VALUE
		u_curds(char *name, int UNUSED count, VALUE UNUSED **vals)

	c) The return value is the function must be a VALUE.

	   The typical way to form a VALUE to return is by declaring
	   the following local variable:

		VALUE result;	/* what we will return */

	d) You will need to include:

		#if defined(CUSTOM)

		/* any #include <foobar.h> here */

		#include "../have_const.h"
		#include "../value.h"
		#include "custom.h"

		#include "../have_unused.h"

	    Typically these will be included just below any system
	    includes and just below the #if defined(CUSTOM) line.

    To better understand the VALUE type, read:

	../value.h

    The VALUE is a union of major value types found inside calc.
    The v_type VALUE element determines which union element is
    being used.	  Assume that we have:

	VALUE *vp;

    Then the value is determined according to v_type:

	vp->v_type	the value is	which is a	type defined in
	----------	------------	----------	---------------
	V_NULL		(none)		n/a		n/a
	V_INT		vp->v_int	long		n/a
	V_NUM		vp->v_num	NUMBER *	../qmath.h
	V_COM		vp->v_com	COMPLEX *	../cmath.h
	V_ADDR		vp->v_addr	VALUE *		../value.h
	V_STR		vp->v_str	char *		n/a
	V_MAT		vp->v_mat	MATRIX *	../value.h
	V_LIST		vp->v_list	LIST *		../value.h
	V_ASSOC		vp->v_assoc	ASSOC *		../value.h
	V_OBJ		vp->v_obj	OBJECT *	../value.h
	V_FILE		vp->v_file	FILEID		../value.h
	V_RAND		vp->v_rand	RAND *		../zrand.h
	V_RANDOM	vp->v_random	RANDOM *	../zrandom.h
	V_CONFIG	vp->v_config	CONFIG *	../config.h
	V_HASH		vp->v_hash	HASH *		../hash.h
	V_BLOCK		vp->v_block	BLOCK *		../block.h

    The V_OCTET is under review and should not be used at this time.

    There are a number of macros that may be used to determine
    information about the numerical values (ZVALUE, NUMBER and COMPLEX).
    you might also want to read the following to understand
    some of the numerical types of ZVALUE, NUMBER and COMPLEX:

	../zmath.h
	../qmath.h
	../cmath.h

    While we cannot go into full detail here are some cookbook
    code for manipulating VALUEs.  For these examples assume
    that we will manipulate the return value:

	VALUE result;	/* what we will return */

    To return NULL:

	result.v_type = V_NULL;
	return result;

    To return a long you need to convert it to a NUMBER:

	long variable;

	result.v_type = V_NUM;
	result.v_num = itoq(variable);		/* see ../qmath.c */
	return result;

    To return a FULL you need to convert it to a NUMBER:

	FULL variable;

	result.v_type = V_NUM;
	result.v_num = utoq(variable);		/* see ../qmath.c */
	return result;

    To convert a ZVALUE to a NUMBER*:

	ZVALUE variable;

	result.v_type = V_NUM;
	result.v_num = qalloc();		/* see ../qmath.c */
	result.v_num->num = variable;
	return result;

    To convert a small NUMBER* into a long:

	NUMBER *num;
	long variable;

	variable = qtoi(num);

    To obtain a ZVALUE from a NUMBER*, extract the numerator:

	NUMBER *num;
	ZVALUE z_variable;

	if (qisint(num)) {
		z_variable = num->num;
	}

    To be sure that the value will fit, use the ZVALUE test macros:

	ZVALUE z_num;
	long variable;
	unsigned long u_variable;
	FULL f_variable;
	short very_tiny_variable;

	if (zgtmaxlong(z_num)) {			/* see ../zmath.h */
		variable = ztolong(z_num);
	}
	if (zgtmaxulong(z_num)) {
		u_variable = ztoulong(z_num);
	}
	if (zgtmaxufull(z_num)) {
		f_variable = ztofull(z_num);
	}
	if (zistiny(z_num)) {
		very_tiny_variable = z1tol(z_num);
	}

    You can (and should) add debugging statements to your custom code
    by examining bit 8 of the calc_debug config flag:

	if (conf->calc_debug & CALCDBG_CUSTOM) {
	    fprintf(stderr, "%ssome custom debug note: msg\n",
		(conf->tab_ok ? "\t" : ""),
		((msg == NULL) ? "((NULL))" : msg));
	}

    One is able to set bit 8 by way of the calc command line:

    	calc -D 128

    See the calc man page for details.  One may also set that bit
    while running calc by way of the config() builtin function:

    	config("calc_debug", 128);

    See the help/config file for details on calc_debug.

Step 6: Register the function in the custom interface table

    To allow the custom() builtin to transfer control to your function,
    you need to add an entry into the CONST struct custom cust table
    found in custom/custtbl.c:

	/*
	 * custom interface table
	 *
	 * The order of the elements in struct custom are:
	 *
	 *	{ "xyz", "brief description of the xyz custom function",
	 *	   minimum_args, maximum_args, c_xyz },
	 *
	 * where:
	 *
	 *	minimum_args	an int >= 0
	 *	maximum_args	an int >= minimum_args and <= MAX_CUSTOM_ARGS
	 *
	 * Use MAX_CUSTOM_ARGS for maximum_args is the maximum number of args
	 * is potentially 'unlimited'.
	 *
	 * If the brief description cannot fit on the same line as the name
	 * without wrapping on a 80 col window, the description is probably
	 * too long and will not look nice in the show custom output.
	 */
	CONST struct custom cust[] = {

	#if defined(CUSTOM)


		/*
		 * add your own custom functions here
		 *
		 * We suggest that you sort the entries below by name
		 * so that show custom will produce a nice sorted list.
		 */

		{ "argv", "information about its args, returns arg count",
		 0, MAX_CUSTOM_ARGS, c_argv },

		{ "devnull", "does nothing",
		 0, MAX_CUSTOM_ARGS, c_devnull },

		{ "help", "help for custom functions",
		 1, 1, c_help },

		{ "sysinfo", "return a calc #define value",
		 0, 1, c_sysinfo },


	#endif /* CUSTOM */

		/*
		 * This must be at the end of this table!!!
		 */
		{NULL, NULL,
		 0, 0, NULL}
	};

    The definition of struct custom may be found in custom.h.

    It is important that your entry be placed inside the:

	#if defined(CUSTOM) ... #endif /* CUSTOM */

    lines so that when the custom interface is disabled by the upper
    level Makefile, one does not have unsatisfied symbols.

    The brief description should be brief so that 'show custom' looks well
    formatted.	If the brief description cannot fit on the same line as
    the name without wrapping on a 80 col window, the description is
    probably too long and will not look nice in the show custom output.

    The minargs places a lower bound on the number of args that
    must be supplied to the interface.	This does NOT count
    the name argument given to custom().  So if minargs is 2:

	custom("curds")		/* call blocked at high level interface */
	custom("curds", a)	/* call blocked at high level interface */
	custom("curds", a, b)	/* call passed down to "curds" interface */

    The maxargs sets a limit on the number of args that may be passed.
    If minargs == maxargs, then the call requires a fixed number of
    argument.  There is a upper limit on the number of args.  If
    one wants an effectively unlimited upper bound, use MAX_CUSTOM_ARGS.

    Note that one must have:

		0 <= minargs <= maxargs <= MAX_CUSTOM_ARGS

    To allow the curds function to take at least 2 args and up
    to 5 args, one would add the following entry to cust[]:

		{ "curds", "brief description about curds interface",
		 2, 5, u_curds },

    It is recommended that the cust[] remain in alphabetical order,
    so one would place it before the "devnull" and after "argv".

    Last, you must forward declare the u_curds near the top of the file:

	#if defined(CUSTOM)


	/*
	 * add your forward custom function declarations here
	 *
	 * Declare custom functions as follows:
	 *
	 *	E_FUNC VALUE c_xyz(char*, int, VALUE**);
	 *
	 * We suggest that you sort the entries below by name.
	 */
	E_FUNC VALUE c_argv(char*, int, VALUE**);
	E_FUNC VALUE c_devnull(char*, int, VALUE**);
	E_FUNC VALUE c_help(char*, int, VALUE**);
	E_FUNC VALUE c_sysinfo(char*, int, VALUE**);

    For u_curds we would add the line:

	E_FUNC VALUE u_curds(char*, int, VALUE**);


Step 7: Add the required information to the custom/Makefile.head

    The calc test script, curds.cal, should be added to the
    CUSTOM_CALC_FILES Makefile variable found in custom/Makefile.head:

	CUSTOM_CALC_FILES= argv.cal halflen.cal curds.cal

    The help file, curds, should be added to the CUSTOM_HELP
    custom/Makefile.head variable:

	CUSTOM_HELP= argv devnull help sysinfo curds

    If you needed to create any .h files to support u_curds.c, these
    files should be added to the CUSTOM_H_SRC custom/Makefile.head variable:

	CUSTOM_H_SRC= u_curds.h otherfile.h

    Your u_curds.c file MUST be added to the CUSTOM_SRC custom/Makefile.head
    variable:

	CUSTOM_SRC= c_argv.c c_devnull.c c_help.c c_sysinfo.c u_curds.c

    and so must the associated .o file:

	CUSTOM_OBJ= c_argv.o c_devnull.o c_help.o c_sysinfo.o u_curds.o


Step 8: Compile and link in your code

    If your calc was not previously setup to compile custom code,
    you should set it up now.  The upper level Makefile (and
    the custom Makefile) should have the following Makefile
    variable defined:

	ALLOW_CUSTOM= -DCUSTOM

    It is recommended that you build your code from the top level
    Makefile.  It saves having to sync the other Makefile values.
    To try and build the new libcustcalc.a that contains u_curds.c:

	(cd ..; make custom/libcustcalc.a)

    Fix any compile and syntax errors as needed.  :-)

    Once libcustcalc.a successfully builds, compile calc:

	cd ..
	make calc

    And check to be sure that the regression test suite still
    works without errors:

	make check


Step 9: Add the Make dependency tools

    You should probably add the dependency lines to the bottom of
    the Makefile.  Given the required include files, you will at least
    have the following entries placed at the bottom of the Makefile:

	u_curds.o: ../alloc.h
	u_curds.o: ../block.h
	u_curds.o: ../byteswap.h
	u_curds.o: ../calcerr.h
	u_curds.o: ../cmath.h
	u_curds.o: ../config.h
	u_curds.o: ../endian_calc.h
	u_curds.o: ../hash.h
	u_curds.o: ../have_const.h
	u_curds.o: ../have_malloc.h
	u_curds.o: ../have_newstr.h
	u_curds.o: ../have_stdlib.h
	u_curds.o: ../have_string.h
	u_curds.o: ../longbits.h
	u_curds.o: ../nametype.h
	u_curds.o: ../qmath.h
	u_curds.o: ../shs.h
	u_curds.o: ../value.h
	u_curds.o: ../zmath.h
	u_curds.o: u_curds.c
	u_curds.o: ../custom.h

    If you have the makedepend tool from the X11 development environment
    (by Todd Brunhoff, Tektronix, Inc. and MIT Project Athena), you can
    use the following to update your dependencies:

	# cd to the top level calc directory if you are not there already

	rm -f Makefile.bak custom/Makefile.bak
	make depend

	diff -c Makefile.bak Makefile			# look at the changes
	diff -c custom/Makefile.bak custom/Makefile	# look at the changes

	rm -f Makefile.bak custom/Makefile.bak		# cleanup

Step 10: Test

    Now that you have built calc with your new custom function, test it:

	./calc -C		# run the new calc with the -C arg

    And then try out our test suite:

	C-style arbitrary precision calculator (version 2.10.3t5.1)
	[Type "exit" to exit, or "help" for help.]

	> read custom/curds.cal
	curds(a, b, [c, d, e]) defined

	> custom("curds", 2, 3, 4)


Step 11: Install

    Once you are satisfied that everything works, install the new code:

	# cd to the top level calc directory if you are not there already

	make install

    Although calc does not run setuid, you may need to be root to install
    the directories into which calc installs may be write protected.


Step 12: Contribute

    Your custom function may be of interest to some people and/or
    serve as an example of what one can do with custom functions.

    Read the file:

	help/contrib		(or run:  calc help contrib)

    and consider submitting your custom function for possible
    inclusion in later versions of calc.

## Copyright (C) 1999-2007  Landon Curt Noll
##
## Calc is open software; you can redistribute it and/or modify it under
## the terms of the version 2.1 of the GNU Lesser General Public License
## as published by the Free Software Foundation.
##
## Calc 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.
##
## A copy of version 2.1 of the GNU Lesser General Public License is
## distributed with calc under the filename COPYING-LGPL.  You should have
## received a copy with calc; if not, write to Free Software Foundation, Inc.
## 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
##
## @(#) $Revision: 30.4 $
## @(#) $Id: HOW_TO_ADD,v 30.4 2007/09/21 01:27:27 chongo Exp $
## @(#) $Source: /usr/local/src/bin/calc/custom/RCS/HOW_TO_ADD,v $
##
## Under source code control:	1997/03/10 03:03:21
## File existed as early as:	1997
##
## chongo <was here> /\oo/\	http://www.isthe.com/chongo/
## Share and enjoy!  :-)	http://www.isthe.com/chongo/tech/comp/calc/