diff options
author | Zeev Suraski <zeev@php.net> | 1999-04-07 21:05:13 +0000 |
---|---|---|
committer | Zeev Suraski <zeev@php.net> | 1999-04-07 21:05:13 +0000 |
commit | aceaabceffd537a0ed83fa25e189b08eae585f4a (patch) | |
tree | bcef55f16a2ae57c1c883b34347f9e6906ca6dfe /apidoc.txt | |
parent | d94f3e22ae6fe17d82b189dc362e975a906f919a (diff) | |
download | php-git-aceaabceffd537a0ed83fa25e189b08eae585f4a.tar.gz |
PHP 4.0
Diffstat (limited to 'apidoc.txt')
-rw-r--r-- | apidoc.txt | 492 |
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 |