#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PATHLEN 1024
/*** log ***/
//#define DEBUG
#ifdef DEBUG
#define LOG(format, ...) \
printf("<"__FILE__">(%05d): "format"", __LINE__, ##__VA_ARGS__)
#else
#define LOG(format, ...)
#endif
/*** log end ***/
/*** list ***/
typedef struct _SNode {
struct _SNode * prev;
struct _SNode * next;
char m_acDir[PATHLEN];
}SNode;
typedef struct _SList {
struct _SNode * head;
struct _SNode * tail;
}SList;
SNode * list_node_init(const char * pcDir)
{
SNode * pNode = (SNode*)malloc(sizeof(SNode));
pNode->prev = NULL;
pNode->next = NULL;
if(NULL == pcDir)
{
memset(pNode->m_acDir, 0, sizeof(pNode->m_acDir));
}
else
{
strcpy(pNode->m_acDir, pcDir);
}
return pNode;
}
SList * list_init()
{
SList * pList = (SList*)malloc(sizeof(SList));
SNode * pHead = list_node_init(NULL);
pList->head = pHead;
pList->tail = pHead;
return pList;
}
void list_insert_one_node(SNode * pNewNode, SNode * pPreNode, SNode * pCurNode)
{
pNewNode->prev = pPreNode;
pNewNode->next = pCurNode;
pPreNode->next = pNewNode;
if(pCurNode != NULL)
{
pCurNode->prev = pNewNode;
}
}
void list_delete_one_node(SNode * pNode)
{
if(NULL == pNode) {
return ;
}
SNode * pPreNode = pNode->prev;
SNode * pNextNode = pNode->next;
pPreNode->next = pNextNode;
if(pNextNode != NULL) {
pNextNode->prev = pPreNode;
}
free(pNode);
}
void list_insert_node_tail(SList * pList, SNode * pNode)
{
list_insert_one_node(pNode, pList->tail, NULL);
pList->tail = pNode;
}
void list_insert_tail(SList * pList, const char * pcData)
{
SNode * pNode = list_node_init(pcData);
list_insert_node_tail(pList, pNode);
}
SList * list_join(SList * first, SList * second)
{
SList * pNewList = list_init();
pNewList->tail->next = first->head->next;
first->head->next->prev = pNewList->tail;
first->tail->next = second->head->next;
second->head->next->prev = first->tail;
first->head->next = NULL;
first->tail = first->head;
second->head->next = NULL;
second->tail = second->head;
return pNewList;
}
void list_destroy(SList * pList)
{
if(NULL == pList) {
return ;
}
SNode * pCur = pList->head->next;
while (pCur != NULL)
{
SNode * pNext = pCur->next;
free(pCur);
pCur = pNext;
}
free(pList);
}
void list_print(SList * pList)
{
#ifdef DEBUG
SNode * pCur = pList->head->next;
while (pCur != NULL)
{
printf("%s ", pCur->m_acDir);
pCur = pCur->next;
}
printf("\n");
#endif
}
/*** list end ***/
SList * pstChangePathToList(const char * pcPath)
{
SList * pList = list_init();
char acPath[PATHLEN] = {0};
strcpy(acPath, pcPath);
char * pStart = acPath;
if(pStart[0] == '/') //absolute path
{
list_insert_tail(pList, "/");
pStart++;
}
while (*pStart != '\0')
{
char * pEnd = strchr(pStart, '/');
if(NULL == pEnd) //last one dir
{
list_insert_tail(pList, pStart);
break;
}
else
{
if( pEnd == pStart ) //serial '/'
{
pStart++;
}
else
{
*pEnd = '\0';
list_insert_tail(pList, pStart);
pStart = pEnd + 1;
}
}
}
list_print(pList);
return pList;
}
void vTrimAbsolutePath(SList * pList, char * pcPath)
{
SNode * pCur = pList->head->next->next;
if(NULL == pCur)
{
strcpy(pcPath, "/");
return ;
}
//delete '.' and '..'
while (pCur != NULL)
{
if( strcmp(".", pCur->m_acDir) == 0 )
{
SNode * pNext = pCur->next;
list_delete_one_node(pCur);
pCur = pNext;
}
else if( strcmp("..", pCur->m_acDir) == 0 )
{
SNode * pNext = pCur->next;
list_delete_one_node(pCur);
pCur = pNext;
if(pCur != NULL && pCur->prev != pList->head->next) { //if prev is root '/'
list_delete_one_node(pCur->prev);
}
}
else
{
pCur = pCur->next;
}
}
pCur = pList->head->next->next;
if(NULL == pCur)
{
strcpy(pcPath, "/");
return ;
}
while (pCur != NULL)
{
strcat(pcPath, "/");
strcat(pcPath, pCur->m_acDir);
pCur = pCur->next;
}
}
void vTrimRelativePath(SList * pCurList, SList * pSrcList, char * pcPath)
{
SList * pList = list_join(pCurList, pSrcList);
vTrimAbsolutePath(pList, pcPath);
list_destroy(pList);
}
void vGetAbsolutePath(const char * pcCurPath, const char * pcSrc, char * pcDst)
{
if(NULL == pcCurPath || NULL == pcSrc || NULL == pcDst) {
return ;
}
LOG("pcCurPath: %s\n", pcCurPath);
LOG("pcSrc: %s\n", pcSrc);
SList * pCurList = pstChangePathToList(pcCurPath);
SList * pSrcList = pstChangePathToList(pcSrc);
if(pcSrc[0] == '/') //absolute path
{
vTrimAbsolutePath(pSrcList, pcDst);
}
else //relative path
{
vTrimRelativePath(pCurList, pSrcList, pcDst);
}
list_destroy(pCurList);
list_destroy(pSrcList);
}
int main()
{
int n = 0;
char acCurPath[PATHLEN] = {0};
scanf("%d", &n);
scanf("%s", acCurPath);
for (int i = 0; i < n; i++)
{
char acSrcPath[PATHLEN] = {0};
char acDstPath[PATHLEN] = {0};
scanf("%s", acSrcPath);
vGetAbsolutePath(acCurPath, acSrcPath, acDstPath);
LOG("acDstPath: %s\n\n", acDstPath);
printf("%s\n", acDstPath);
}
return 0;
}