X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=Introduction-to-QuakeC.md;h=aaa5fe20cc0df577a13e510f7da0a95112666199;hb=9e828737e3f6832afbc624e7c2ce449f28050617;hp=bf7071169ee1b0514ed5b1ba2f4af372ab723b74;hpb=0015bfa8f1aa78080ded738eb82208b82b1982c0;p=xonotic%2Fxonotic.wiki.git diff --git a/Introduction-to-QuakeC.md b/Introduction-to-QuakeC.md index bf70711..aaa5fe2 100644 --- a/Introduction-to-QuakeC.md +++ b/Introduction-to-QuakeC.md @@ -1,16 +1,25 @@ QuakeC ====== -Article TODO ------------- - -- expand explanations - About QuakeC ------------ QuakeC is a very simplified dialect of the well-known C programming language, and is used by the Quake I engine and its derivatives. Xonotic uses the GMQCC dialect of QuakeC, so only this dialect will be described (as well as some common extensions among Quake engines). +There are several documents describing the original version of QC as used in Quake 1: +- an [old version](http://www.gamers.org/dEngine/quake/spec/quake-spec34/index1.htm) which is a part of unofficial [Quake Documentation](http://www.gamers.org/dEngine/quake/spec/quake-spec34/) +- a probably slightly [newer version](http://www.cataboligne.org/extra/qcmanual.html) +- a [newer and extended version](http://pages.cs.wisc.edu/~jeremyp/quake/quakec/quakec.pdf) in PDF + +Even this page is outdated and incomplete, not all GMQCC QuakeC constructs are described here and some of the bugs mentioned here have already been fixed. + +Other resources +--------------- + +- [QC Tutorial for Absolute Beginners](https://web.archive.org/web/20091118154016/http://forums.inside3d.com/viewtopic.php?t=1286) +- [List of builtins on quakewiki.org](https://quakewiki.org/wiki/List_of_builtin_functions) +- comments and `doc.md` in the `qcsrc/dpdefs` directory + Example code ------------ @@ -57,17 +66,6 @@ entity findnearestspawn(vector v) **Note:** *findchain* is implemented in QuakeC for demonstration purposes only so one can see how to build a linked list, as this function is already built in to the engine and can be used directly -Other resources ---------------- - -Here is a forum on Inside3D where you can read more about QuakeC and ask questions: -- QuakeC Forum on Inside3D: http://forums.inside3d.com/viewforum.php?f=2 -- QC Tutorial for Absolute Beginners: http://forums.inside3d.com/viewtopic.php?t=1286 - -For available functions in QuakeC, look in the following places: -- The Quakery: http://quakery.quakedev.com/qwiki/index.php/List_of_builtin_functions -- Xonotic source: [builtins.qh](http://git.xonotic.org/?p=xonotic/xonotic-data.pk3dir.git;a=blob_plain;f=qcsrc/server/builtins.qh;hb=HEAD) for Quake functions, [extensions.qh](http://git.xonotic.org/?p=xonotic/xonotic-data.pk3dir.git;a=blob_plain;f=qcsrc/server/extensions.qh;hb=HEAD) for DarkPlaces extensions - Variables ========= @@ -154,7 +152,17 @@ A *string* in QuakeC is an immutable reference to a null-terminated character st The offset defines from which starting position to search, and the return value is `–1` if no match is found. The offset returned is *0*-based, and to search in the whole string, a start offset of *0* would be used. -- **substring(string, startpos, length)** returns part of a string. The offset is *0*-based here, too. +- **strreplace(old, new, string)** searches for certain characters in a string and replaces them with other characters, as in: + ```c + strreplace("de", "con", "destruction") == "construction"; + ``` + +- **substring(string, startpos, length)** returns part of a string. + +The offset is *0*-based here, too. A length of `-1` designates the end of the string (it will return the part of the string after the start position), a length of `-2` designates the penultimate character of the string, and so on. + +- **strtoupper(string)** capitalizes a string. +- **strtolower(string)** lowercases a string. Note that there are different kinds of *strings*, regarding memory management: @@ -246,9 +254,12 @@ float sum3(float a, float b, float c) However, the syntax to declare function pointers is simplified: ```c +// in global scope typedef float(float, float, float) op3func_t; var float(float a, float b, float c) f; op3func_t g; + +// in local scope f = sum3; g = f; print(ftos(g(1, 2, 3)), "\n"); // prints 6 @@ -270,6 +281,24 @@ A special kind of functions are the built-in functions, which are defined by the string strcat(string a, string b, ...) = #115; ``` +The function/field syntax is ambiguous. In global scope a declaration can be a variable, field or function. In local scope, it's always a variable. The `var` keyword can be used in global scope to treat it as local scope (always declaring a variable). The following table shows declarations in global scope: + +| Example code | Meaning | +|--------------|---------| +| `.float a;` | Entity field of type `float` | +| `float(float x1) a;` or `float a(float x1);` | Function with a `float` param returning `float` | +| `.float a(float x1);` | Function with a float param returning a `float` field reference | +| `.float(float x1) a;` | Entity field of type function with a `float` param returning `float` | +| `.float(float x1) a(float x2);` | Function with a `float` param returning a field reference of type function with a `float` param returning `float` | + +These rules were determined by experimenting with GMQCC: +- if there are parentheses after the name, it's always a function +- else if it starts with a period, it's a field +- else if there are parentheses after the type, it's a function (using the old QC syntax) +- else it's a variable + +GMQCC allows even weirder declarations like `float f(float)();` which can be called as `f()(42);`. It's not clear whether this behavior is intentional or the result of one of the many compiler bugs. + void ----