#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "list.h"

struct ListNode {

	int val;
	struct ListNode *next;
};

/*
 * [in]
 * @nd1: linked list of nodes
 * @nd2: linked list of nodes
 * 
 * [out]
 * none
 *
 * [in/out]
 * @carry(in): carry value of last sum
 * @carry(out): carry value of current sum
 */
static struct ListNode *addTwoNodes(struct ListNode *nd1,
				    struct ListNode *nd2,
				    int *carry)
{
	struct ListNode *nd_sum = malloc(sizeof(struct ListNode));

	if (!nd_sum) {
		printf("malloc node failed\n");
		return NULL;
	}
	nd_sum->val = 0;
	nd_sum->next = NULL;

	nd_sum->val = (nd1->val + nd2->val + *carry) % 10;
	*carry = (nd1->val + nd2->val + *carry) / 10;

	return nd_sum;
}

struct ListNode *addTwoNumbers(struct ListNode *l1, struct ListNode *l2)
{
	struct ListNode *nd1 = l1;
	struct ListNode *nd2 = l2;
	struct ListNode *nd_cont = NULL;
	struct ListNode nd_zero = { 0, NULL };

	struct ListNode *l_head = NULL;
	struct ListNode *l_tail = l_head;
	struct ListNode *nd_sum = NULL;
	int carry = 0;

	while (nd1 && nd2) {
		nd_sum = addTwoNodes(nd1, nd2, &carry);
		if (!nd_sum)
			return NULL;
		
		if (!l_head) { /* empty list */
			l_tail = l_head = nd_sum;
		} else { /* l_tail keeps track of the last node of list */
			l_tail->next = nd_sum;
			l_tail = nd_sum;
		}

		nd1 = nd1->next;
		nd2 = nd2->next;
	}

	if (!nd1 && !nd2) {
		goto carry;
	} else if (nd1 && !nd2) {
		nd_cont = nd1;
	} else { /* !nd1 && nd2 */
		nd_cont = nd2;
	}

	while (nd_cont) {
		nd_sum = addTwoNodes(nd_cont, &nd_zero, &carry);
		if (!nd_sum)
			return NULL;

		if (!l_head) { /* in case one of the two lists is initially empty */
			l_tail = l_head = nd_sum;
		} else {
			l_tail->next = nd_sum;
			l_tail = nd_sum;
		}

		nd_cont = nd_cont->next;
	}

carry:
	if (carry) {
		nd_sum = malloc(sizeof(struct ListNode));
		if (!nd_sum)
			return NULL;
		nd_sum->val = carry;
		nd_sum->next = NULL;

		l_tail->next = nd_sum;
		l_tail = nd_sum;
	}

	return l_head;
}

References

[1] https://leetcode.com/problems/add-two-numbers