summaryrefslogtreecommitdiff
path: root/apidoc.txt
diff options
context:
space:
mode:
authorZeev Suraski <zeev@php.net>1999-04-07 21:05:13 +0000
committerZeev Suraski <zeev@php.net>1999-04-07 21:05:13 +0000
commitaceaabceffd537a0ed83fa25e189b08eae585f4a (patch)
treebcef55f16a2ae57c1c883b34347f9e6906ca6dfe /apidoc.txt
parentd94f3e22ae6fe17d82b189dc362e975a906f919a (diff)
downloadphp-git-aceaabceffd537a0ed83fa25e189b08eae585f4a.tar.gz
PHP 4.0
Diffstat (limited to 'apidoc.txt')
-rw-r--r--apidoc.txt492
1 files changed, 492 insertions, 0 deletions
diff --git a/apidoc.txt b/apidoc.txt
new file mode 100644
index 0000000000..b24961be9a
--- /dev/null
+++ b/apidoc.txt
@@ -0,0 +1,492 @@
+PHP Version 3.0 API Documentation
+
+Table of Contents
+-----------------
+ 1. Function Prototype
+ 2. Function Arguments
+ 3. Variable number of function arguments
+ 4. Using the function arguments
+ 5. Memory management in functions
+ 6. Setting variables in the symbol table
+ 7. Returning values from functions
+ 8. Returning 'complex' values from functions (arrays or objects)
+ 9. Using the resource list
+10. Using the persistent resource table
+11. Adding runtime configuration directives
+-----------------
+
+1. Function Prototype
+
+ All functions look like this:
+
+ void php3_foo(INTERNAL_FUNCTION_PARAMETERS) {
+
+ }
+
+ Even if your function doesn't take any arguments, this is how it is
+ called.
+
+-----------------
+
+2. Function Arguments
+
+ Arguments are always of type pval. This type contains a union which
+ has the actual type of the argument. So, if your function takes two
+ arguments, you would do something like the following at the top of your
+ function:
+
+ pval *arg1, *arg2;
+ if (ARG_COUNT(ht) != 2 || getParameters(ht,2,&arg1,&arg2)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ NOTE: Arguments can be passed either by value or by reference. In both
+ cases you will need to pass &(pval *) to getParameters. If you want to
+ check if the n'th parameter was sent to you by reference or not, you can
+ use the function, ParameterPassedByReference(ht,n). It will return either
+ 1 or 0.
+
+ When you change any of the passed parameters, whether they are sent by
+ reference or by value, you can either start over with the parameter by
+ calling pval_destructor on it, or if it's an ARRAY you want to add to,
+ you can use functions similar to the ones in internal_functions.h which
+ manipulate return_value as an ARRAY.
+
+ Also if you change a parameter to IS_STRING make sure you first assign
+ the new estrdup'ed string and the string length, and only later change the
+ type to IS_STRING. If you change the string of a parameter which already
+ IS_STRING or IS_ARRAY you should run pval_destructor on it first.
+
+-----------------
+
+3. Variable number of function arguments
+
+ A function can take a variable number of arguments. If your function can
+ take either 2 or 3 arguments, use the following:
+
+ pval *arg1, *arg2, *arg3;
+ int arg_count = ARG_COUNT(ht);
+
+ if (arg_count<2 || arg_count>3 ||
+ getParameters(ht,arg_count,&arg1,&arg2,&arg3)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+------------------
+
+4. Using the function arguments
+
+ The type of each argument is stored in the pval type field:
+
+
+ This type can be any of the following:
+
+ IS_STRING String
+ IS_DOUBLE Double-precision floating point
+ IS_LONG Long
+ IS_ARRAY Array
+
+ IS_EMPTY ??
+ IS_USER_FUNCTION ??
+ IS_INTERNAL_FUNCTION ?? (if some of these cannot be passed to a
+ function - delete)
+ IS_CLASS ??
+ IS_OBJECT ??
+
+ If you get an argument of one type and would like to use it as another,
+ or if you just want to force the argument to be of a certain type, you
+ can use one of the following conversion functions:
+
+ convert_to_long(arg1);
+ convert_to_double(arg1);
+ convert_to_string(arg1);
+ convert_to_boolean_long(arg1); If the string is "" or "0" it
+ becomes 0, 1 otherwise
+ convert_string_to_number(arg1); Converts string to either LONG or
+ DOUBLE depending on string
+
+ These function all do in-place conversion. They do not return anything.
+
+ The actual argument is stored in a union.
+
+ For type IS_STRING, use arg1->value.str.val
+ IS_LONG arg1->value.lval
+ IS_DOUBLE arg1->value.dval
+
+-------------------
+
+5. Memory management in functions
+
+ Any memory needed by a function should be allocated with either emalloc()
+ or estrdup(). These are memory handling abstraction functions that look
+ and smell like the normal malloc() and strdup() functions. Memory should
+ be freed with efree().
+
+ There are two kinds of memory in this program. Memory which is returned
+ to the parser in a variable and memory which you need for temporary
+ storage in your internal function. When you assign a string to a
+ variable which is returned to the parser you need to make sure you first
+ allocate the memory with either emalloc or estrdup. This memory
+ should NEVER be freed by you, unless you later, in the same function
+ overwrite your original assignment (this kind of programming practice is
+ not good though).
+
+ For any temporary/permanent memory you need in your functions/library you
+ should use the three emalloc(), estrdup(), and efree() functions. They
+ behave EXACTLY like their counterpart functions. Anything you emalloc()
+ or estrdup() you have to efree() at some point or another, unless it's
+ supposed to stick around until the end of the program, otherwise there
+ will be a memory leak. The meaning of "the functions behave exactly like
+ their counterparts" is if you efree() something which was not
+ emalloc()'ed nor estrdup()'ed you might get a segmentation fault. So
+ please take care and free all of your wasted memory. One of the biggest
+ improvements in PHP 3.0 will hopefully be the memory management.
+
+ If you compile with "-DDEBUG", PHP3 will print out a list of all
+ memory that was allocated using emalloc() and estrdup() but never
+ freed with efree() when it is done running the specified script.
+
+-------------------
+
+6. Setting variables in the symbol table
+
+ A number of macros are available which make it easier to set a variable
+ in the symbol table:
+
+ SET_VAR_STRING(name,value) **
+ SET_VAR_DOUBLE(name,value)
+ SET_VAR_LONG(name,value)
+
+ ** Be careful here. The value part must be malloc'ed manually because
+ the memory management code will try to free this pointer later. Do
+ not pass statically allocated memory into a SET_VAR_STRING
+
+ Symbol tables in PHP 3.0 are implemented as hash tables. At any given time,
+ &symbol_table is a pointer to the 'main' symbol table, and active_symbol_table
+ points to the currently active symbol table (these may be identical like in
+ startup, or different, if you're inside a function).
+
+ The following examples use 'active_symbol_table'. You should replace it with
+ &symbol_table if you specifically want to work with the 'main' symbol table.
+ Also, the same funcions may be applied to arrays, as explained below.
+
+ * To check whether a variable named $foo already exists in a symbol table:
+ if (hash_exists(active_symbol_table,"foo",sizeof("foo"))) { exists... }
+ else { doesn't exist }
+
+ * If you also need to get the type of the variable, you can use:
+ hash_find(active_symbol_table,"foo",sizeof("foo"),&pvalue);
+ check(pvalue.type);
+
+ Arrays in PHP 3.0 are implemented using the same hashtables as symbol tables.
+ This means the two above functions can also be used to check variables
+ inside arrays.
+
+ If you want to define a new array in a symbol table, you should do this:
+
+ 1. Possibly check it exists and abort, using hash_exists()
+ or hash_find().
+ 2. Code:
+
+ pval arr;
+
+ if (array_init(&arr) == FAILURE) { failed... };
+ hash_update(active_symbol_table,"foo",sizeof("foo"),&arr,sizeof(pval),NULL);
+
+ This code declares a new array, named $foo, in the active symbol table.
+ This array is empty.
+
+ Here's how to add new entries to it:
+
+ pval entry;
+
+ entry.type = IS_LONG;
+ entry.value.lval = 5;
+
+ hash_update(arr.value.ht,"bar",sizeof("bar"),&entry,sizeof(pval),NULL); /* defines $foo["bar"] = 5 */
+ hash_index_update(arr.value.ht,7,&entry,sizeof(pval),NULL); /* defines $foo[7] = 5 */
+ hash_next_index_insert(arr.value.ht,&entry,sizeof(pval),NULL); /* defines the next free place in $foo[],
+ * $foo[8], to be 5 (works like php2)
+ */
+
+ If you'd like to modify a value that you inserted to a hash, you must first retreive it from the hash. To
+ prevent that overhead, you can supply a pval ** to the hash add function, and it'll be updated with the
+ pval * address of the inserted element inside the hash. If that value is NULL (like in all of the
+ above examples) - that parameter is ignored.
+
+ hash_next_index_insert() works more or less using the same logic
+ "$foo[] = bar;" works in PHP 2.0.
+
+ If you are building an array to return from a function, you can initialize
+ the array just like above by doing:
+
+ if (array_init(return_value) == FAILURE) { failed...; }
+
+ and then adding values with the helper functions:
+
+ add_next_index_long(return_value,long_value);
+ add_next_index_double(return_value,double_value);
+ add_next_index_string(return_value,estrdup(string_value));
+
+ Of course, if the adding isn't done right after the array
+ initialization, you'd probably have to look for the array first:
+
+ pval *arr;
+
+ if (hash_find(active_symbol_table,"foo",sizeof("foo"),(void **)&arr)==FAILURE) { can't find... }
+ else { use arr->value.ht... }
+
+ Note that hash_find receives a pointer to a pval pointer, and
+ not a pval pointer.
+
+ Just about any hash function returns SUCCESS or FAILURE (except for
+ hash_exists() that returns a boolean truth value).
+
+-------------------
+
+7. Returning 'simple' values from functions (integers, floats or strings)
+
+ A number of macros are available to make it easier to return things from
+ functions:
+
+ These set the return value and return from the function:
+
+ RETURN_FALSE
+ RETURN_TRUE
+ RETURN_LONG(l)
+ RETURN_STRING(s,dup) If dup is true, duplicates the string
+ RETURN_STRINGL(s,l,dup) Return string (s) specifying length (l).
+ RETURN_DOUBLE(d)
+
+ These only set the return value:
+
+ RETVAL_FALSE
+ RETVAL_TRUE
+ RETVAL_LONG(l)
+ RETVAL_STRING(s,dup) If dup is true, duplicates the string
+ RETVAL_STRINGL(s,l,dup) Return string (s) specifying length (l).
+ RETVAL_DOUBLE(d)
+
+ The string macros above will all estrdup() the passed 's' argument,
+ so you can safely free the argument after calling the macro, or
+ alternatively use statically allocated memory.
+
+ If your function returns boolean success/error responses, always use
+ RETURN_TRUE and RETURN_FALSE respectively.
+
+-------------------
+
+8. Returning 'complex' values from functions (arrays or objects)
+
+ Your function can also return a complex data type such as an object
+ or an array.
+
+ Returning an object:
+
+ 1. Call object_init(return_value).
+ 2. Fill it up with values:
+
+ add_property_long(return_value,property_name,l) Add a property named 'property_name', of type long, equals to 'l'
+ add_property_double(return_value,property_name,d) Same, only a double
+ add_property_string(return_value,property_name,str) Same, only a string
+ add_property_stringl(return_value,property_name,str,l) Add a property named 'property_name', of type string, string is 'str' with length 'l'
+
+ 3. Possibly, register functions for this object. In order to
+ obtain values from the object, the function would have to fetch
+ "this" from the active_symbol_table. Its type should be IS_OBJECT,
+ and it's basically a regular hash table (i.e., you can use regular
+ hash functions on .value.ht). The actual registration of the
+ function can be done using:
+
+ add_method(return_value,function_name,function_ptr)
+
+
+ Returning an array:
+
+ 1. Call array_init(return_value).
+ 2. Fill it up with values:
+
+ add_assoc_long(return_value,key,l) add associative entry with key 'key' and long value 'l'
+ add_assoc_double(return_value,key,d)
+ add_assoc_string(return_value,key,str)
+ add_assoc_stringl(return_value,key,str,length) specify the string length
+
+ add_index_long(return_value,index,l) add entry in index 'index' with long value 'l'
+ add_index_double(return_value,index,d)
+ add_index_string(return_value,index,str)
+ add_index_stringl(return_value,index,str,length) specify the string length
+
+ add_next_index_long(return_value,l) add an array entry in the next free offset with long value 'l'
+ add_next_index_double(return_value,d)
+ add_next_index_string(return_value,str)
+ add_next_index_stringl(return_value,str,length) specify the string length
+
+-------------------
+
+9. Using the resource list
+
+ PHP 3.0 has a standard way of dealing with various types of resources,
+ that replaces all of the local linked lists in PHP 2.0.
+
+ Available functions:
+
+ php3_list_insert(ptr, type) returns the 'id' of the newly inserted resource
+ php3_list_delete(id) delete the resource with the specified id
+ php3_list_find(id,*type) returns the pointer of the resource with the specified id, updates 'type' to the resource's type
+
+ Typically, these functions are used for SQL drivers but they can be
+ used for anything else, and are used, for instance, for maintaining
+ file descriptors.
+
+ Typical list code would look like this:
+
+ Adding a new resource:
+
+ RESOURCE *resource;
+
+ ...allocate memory for resource and acquire resource...
+ /* add a new resource to the list */
+ return_value->value.lval = php3_list_insert((void *) resource, LE_RESOURCE_TYPE);
+ return_value->type = IS_LONG;
+
+ Using an existing resource:
+
+ pval *resource_id;
+ RESOURCE *resource;
+ int type;
+
+ convert_to_long(resource_id);
+ resource = php3_list_find(resource_id->value.lval, &type);
+ if (type != LE_RESOURCE_TYPE) {
+ php3_error(E_WARNING,"resource index %d has the wrong type",resource_id->value.lval);
+ RETURN_FALSE;
+ }
+ ...use resource...
+
+ Deleting an existing resource:
+
+ pval *resource_id;
+ RESOURCE *resource;
+ int type;
+
+ convert_to_long(resource_id);
+ php3_list_delete(resource_id->value.lval);
+
+
+ The resource types should be registered in php3_list.h, in enum
+ list_entry_type. In addition, one should add shutdown code for any
+ new resource type defined, in list.c's list_entry_destructor() (even if
+ you don't have anything to do on shutdown, you must add an empty case).
+
+-------------------
+
+10. Using the persistent resource table
+
+ PHP 3.0 has a standard way of storing persistent resources (i.e.,
+ resources that are kept in between hits). The first module to use
+ this feature was the MySQL module, and mSQL followed it, so one can
+ get the general impression of how a persistent resource should be
+ used by reading mysql.c. The functions you should look at are:
+ php3_mysql_do_connect()
+ php3_mysql_connect()
+ php3_mysql_pconnect()
+
+ The general idea of persistence modules is this:
+ 1. Code all of your module to work with the regular resource list
+ mentioned in section (9).
+ 2. Code extra connect functions that check if the resource already
+ exists in the persistent resource list. If it does, register it
+ as in the regular resource list as a pointer to the persistent
+ resource list (because of 1., the rest of the code
+ should work immediately). If it doesn't, then create it, add it
+ to the persistent resource list AND add a pointer to it from the
+ regular resource list, so all of the code would work since it's
+ in the regular resource list, but on the next connect, the
+ resource would be found in the persistent resource list and be
+ used without having to recreate it.
+ You should register these resources with a different type (e.g.
+ LE_MYSQL_LINK for non-persistent link and LE_MYSQL_PLINK for
+ a persistent link).
+
+ If you read mysql.c, you'll notice that except for the more complex
+ connect function, nothing in the rest of the module has to be changed.
+
+ The very same interface exists for the regular resource list and the
+ persistent resource list, only 'list' is replaced with 'plist':
+
+ php3_plist_insert(ptr, type) returns the 'id' of the newly inserted resource
+ php3_plist_delete(id) delete the resource with the specified id
+ php3_plist_find(id,*type) returns the pointer of the resource with the specified id, updates 'type' to the resource's type
+
+ However, it's more than likely that these functions would prove
+ to be useless for you when trying to implement a persistent module.
+ Typically, one would want to use the fact that the persistent resource
+ list is really a hash table. For instance, in the MySQL/mSQL modules,
+ when there's a pconnect() call (persistent connect), the function
+ builds a string out of the host/user/passwd that were passed to the
+ function, and hashes the SQL link with this string as a key. The next
+ time someone calls a pconnect() with the same host/user/passwd, the
+ same key would be generated, and the function would find the SQL link
+ in the persistent list.
+
+ Until further documented, you should look at mysql.c or msql.c to
+ see how one should use the plist's hash table abilities.
+
+ One important thing to note: resources going into the persistent
+ resource list must *NOT* be allocated with PHP's memory manager, i.e.,
+ they should NOT be created with emalloc(), estrdup(), etc. Rather,
+ one should use the regular malloc(), strdup(), etc. The reason for
+ this is simple - at the end of the request (end of the hit), every
+ memory chunk that was allocated using PHP's memory manager is deleted.
+ Since the persistent list isn't supposed to be erased at the end
+ of a request, one mustn't use PHP's memory manager for allocating
+ resources that go to it.
+
+ Shutting down persistent resources:
+
+ When you register resource that's going to be in the persistent list,
+ you should add destructors to it both in the non-persistent list
+ and in the persistent list.
+ The destructor in the non-persistent list destructor shouldn't do anything.
+ The one in the persistent list destructor should properly free any
+ resources obtained by that type (e.g. memory, SQL links, etc). Just like
+ with the non-persistent resources, you *MUST* add destructors for every
+ resource, even it requires no destructotion and the destructor would
+ be empty.
+ Remember, since emalloc() and friends aren't to be used in conjunction
+ with the persistent list, you mustn't use efree() here either.
+
+-------------------
+
+11. Adding runtime configuration directives
+
+Many of the features of PHP3 can be configured at runtime. These
+configuration directives can appear in either the designated php3.ini
+file, or in the case of the Apache module version in the Apache .conf
+files. The advantage of having them in the Apache .conf files is that
+they can be configured on a per-directory basis. This means that one
+directory may have a certain safemodeexecdir for example, while another
+directory may have another. This configuration granularity is especially
+handy when a server supports multiple virtual hosts.
+
+The steps required to add a new directive:
+
+ 1. Add directive to php3_ini_structure struct in mod_php3.h.
+
+ 2. In main.c, edit the php3_module_startup function and add the
+ appropriate cfg_get_string() or cfg_get_long() call.
+
+ 3. Add the directive, restrictions and a comment to the php3_commands
+ structure in mod_php3.c. Note the restrictions part. RSRC_CONF are
+ directives that can only be present in the actual Apache .conf files.
+ Any OR_OPTIONS directives can be present anywhere, include normal
+ .htaccess files.
+
+ 4. In either php3take1handler() or php3flaghandler() add the appropriate
+ entry for your directive.
+
+ 5. In the configuration section of the _php3_info() function in
+ functions/info.c you need to add your new directive.
+
+ 6. And last, you of course have to use your new directive somewhere.
+ It will be addressable as php3_ini.directive