aboutsummaryrefslogtreecommitdiff
path: root/Linux_C_12/cCrossCallProcedureTable_121.c
blob: 3816e8cb3beac2295abd5d375377050d1cd5040c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/********************************************************************************************
    Clean OS Windows library module version 1.2.1.
    This module is part of the Clean Object I/O library, version 1.2.1,
    for the Windows platform.
********************************************************************************************/

/********************************************************************************************
    About this module:
    Implementation of cross call procedure table.
    In this table a linked list of cross call entries is kept.
    A cross call entry is a pair of a cross call code (CcRq...) number (see intrface_121.h)
    and a pointer to a cross call procedure.
    Routines related to printer handling.
********************************************************************************************/
#include "cCrossCallProcedureTable_121.h"
#include <stdlib.h>

/*
 * A CrossCallEntry contains a CcRq number and a pointer to a
 * CrossCallProcedure.
 */
struct _crosscallentry
{
    int					cce_code;	/* CcRq... number */
    CrossCallProcedure	cce_proc;   /* The procedure to be called in case of
                                       cce_code */
    CrossCallEntry		cce_next;	/* The next entry in the list */
};

/*
 * A CrossCallProcedureTable contains a linked list of CrossCallEntries.
 */
struct _crosscallproceduretable
{	int                 ccpt_size;		// nr of entries
    CrossCallEntry		ccpt_first;		// first entry
    CrossCallEntry		ccpt_last;		// last entry
};


/* NewCrossCallEntry creates a CrossCallEntry with cce_next field NULL. */
CrossCallEntry NewCrossCallEntry (int cce_code, CrossCallProcedure cce_proc)
{
    CrossCallEntry cce;
    /* printf("NewCrossCallEntry\n"); */
    cce = rmalloc (sizeof (struct _crosscallentry));

    cce->cce_code = cce_code;
    cce->cce_proc = cce_proc;
    cce->cce_next = NULL;

    return cce;
}

/* FreeCrossCallEntry frees a CrossCallEntry. */
void FreeCrossCallEntry (CrossCallEntry cce)
{
    /* printf("FreeCrossCallEntry\n"); */
    rfree (cce);
}

/* EmptyCrossCallProcedureTable creates an empty table. */
CrossCallProcedureTable EmptyCrossCallProcedureTable (void)
{
    CrossCallProcedureTable ccpt;
    /* printf("EmptyCrossCallProcedureTable\n"); */
    ccpt = rmalloc (sizeof (struct _crosscallproceduretable));

    ccpt->ccpt_size  = 0;
    ccpt->ccpt_first = NULL;
    ccpt->ccpt_last  = NULL;

    return ccpt;
}

/*
 * GetCrossCallProcedureTableSize returns the current number of installed
 * cross call procedures.
 */
int GetCrossCallProcedureTableSize (CrossCallProcedureTable ccpt)
{
    /* printf("GetCrossCallProcedureTableSize\n"); */
    return ccpt->ccpt_size;
}

/* FreeCrossCallProcedureTable frees a CrossCallProcedureTable. */
void FreeCrossCallProcedureTable (CrossCallProcedureTable ccpt)
{
    /* printf("FreeCrossCallProcedureTable\n"); */
    rfree (ccpt);
}

/*	SearchCrossCallEntry (nr,entry) returns the first CrossCallEntry
    following/including entry that either:
        matches nr, or
        is the entry after which a new entry with nr should be added, or
        NULL in case nr should be placed before entry.
*/
static CrossCallEntry SearchCrossCallEntry (int nr,CrossCallEntry entry)
{
    /* printf("SearchCrossCallEntry\n"); */
    if (nr == entry->cce_code)
        return entry;				// entry found
    if (nr < entry->cce_code)
        return NULL;				// no entry found
    if (entry->cce_next == NULL)
        return entry;				// last entry; should insert new entry after this one
    if (nr < entry->cce_next->cce_code)
        return entry;				// next entry exceeds nr; should insert new entry after this one
    return SearchCrossCallEntry (nr,entry->cce_next);
}

/*
 * AddCrossCallEntry (table,nr,proc) adds a new entry (nr,proc) if an entry
 * with nr is not already present.
 */
void AddCrossCallEntry (CrossCallProcedureTable ccpt, int cce_code,
                CrossCallProcedure cce_proc)
{
    CrossCallEntry entry;
    /* printf("AddCrossCallEntry\n"); */
    entry = NewCrossCallEntry (cce_code,cce_proc);

    if (ccpt->ccpt_size == 0)
    {	/* table is empty; create entry and add it */
        ccpt->ccpt_size  = 1;
        ccpt->ccpt_first = entry;
        ccpt->ccpt_last  = entry;
    }
    else if (cce_code < ccpt->ccpt_first->cce_code)
    {	/* entry should be inserted before first entry */
        ccpt->ccpt_size += 1;
        entry->cce_next = ccpt->ccpt_first;
        ccpt->ccpt_first= entry;
    }
    else if (cce_code > ccpt->ccpt_first->cce_code)
    {	/* entry could be in table; look for it and add it if not present */
        CrossCallEntry searchCCE;
        searchCCE = SearchCrossCallEntry (cce_code,ccpt->ccpt_first);

        if (searchCCE == NULL)
        {
            /* printf("\'AddCrossCallEntry\' SearchCrossCallEntry returned NULL CrossCallEntry"); */
            exit(1);
        }
        if (searchCCE->cce_code != cce_code)
        {	/* entry not in table but should be linked after searchCCE */
            gboolean appendLast = (ccpt->ccpt_last == searchCCE);
            ccpt->ccpt_size     += 1;
            entry->cce_next     = searchCCE->cce_next;
            searchCCE->cce_next = entry;

            if (appendLast)
                ccpt->ccpt_last  = entry;	// adjust last if entry is appended at end
        }
    }
}

/* AddCrossCallEntries (table,entries) adds the entries to table */
void AddCrossCallEntries (CrossCallProcedureTable theTable, CrossCallProcedureTable entries)
{
    CrossCallEntry cce;
    /* printf("AddCrossCallEntries\n"); */
    cce = entries->ccpt_first;

    while (cce != NULL)
    {
        AddCrossCallEntry (theTable, cce->cce_code, cce->cce_proc);
        cce = cce->cce_next;
    }
}

/*
 * FindCrossCallEntry returns the found CrossCallProcedure or NULL if not found.
 */
CrossCallProcedure FindCrossCallEntry (CrossCallProcedureTable ccpt, int cce_code)
{
    /* printf("FindCrossCallEntry\n"); */
    if (ccpt->ccpt_size == 0)
    {   /* table is empty, return NULL */
        return NULL;
    }
    else
    {
        CrossCallEntry searchCCE;
        searchCCE = SearchCrossCallEntry (cce_code,ccpt->ccpt_first);
        if (searchCCE && searchCCE->cce_code == cce_code)
            return searchCCE->cce_proc;
        else
            return NULL;
    }
}