Weapons are fired in the weapon's think function. There is a global itemlist, declared in g_items.c. All types of items are declared there and those items, which are weapons, has a weaponthink function pointer setup to point at a function inside p_weapon.c. These functions are called from Think_Weapon, which is called from ClientThink and ClientEndServerFrame. ClientThink only calls Think_Weapon if the player is pressing the attack button. However, to animate the weapon, when not firing it, ClientEndServerFrame calls Think_Weapon every server frame if it hasn't been called in ClientThink.
The currently selected weapon is pointed at from client_persistant_t's weapon pointer. It points to an item in the global itemlist.
Generally, all weapons rely on a couple of attributes in gclient_t to animate and control the weapon. The weaponstate attribute of gclient_t is used to track if the weapon is firing, being prepared to use, etc. The gunframe attribute of the player_state_t is used to track which animation frame is being played to the client. In addition to these two, some weapons use
The ammunition, used by the currently selected weapon, is defined by client_persistant_t's ammo_index. It is an index into the inventory of client_persistant_t. When the different weapons are fired they decrese the number of items in the inventory.