]> git.xonotic.org Git - xonotic/xonotic.wiki.git/blobdiff - Introduction-to-QuakeC.md
Update descriptions
[xonotic/xonotic.wiki.git] / Introduction-to-QuakeC.md
index bf7071169ee1b0514ed5b1ba2f4af372ab723b74..e52a160477522955963e2fba92e40dcdfec4823d 100644 (file)
@@ -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
 =========
 
@@ -246,9 +244,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 +271,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 is 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
 ----