]>
Commit | Line | Data |
---|---|---|
a71ece51 | 1 | /* model.c |
2c9e3090 | 2 | * Greg Cook, 26/Jul/2016 |
a71ece51 | 3 | */ |
4 | ||
2c9e3090 | 5 | /* CRC RevEng: arbitrary-precision CRC calculator and algorithm finder |
a78a3d9d | 6 | * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 Gregory Cook |
a71ece51 | 7 | * |
8 | * This file is part of CRC RevEng. | |
9 | * | |
10 | * CRC RevEng is free software: you can redistribute it and/or modify | |
11 | * it under the terms of the GNU General Public License as published by | |
12 | * the Free Software Foundation, either version 3 of the License, or | |
13 | * (at your option) any later version. | |
14 | * | |
15 | * CRC RevEng is distributed in the hope that it will be useful, | |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 | * GNU General Public License for more details. | |
19 | * | |
20 | * You should have received a copy of the GNU General Public License | |
2c9e3090 | 21 | * along with CRC RevEng. If not, see <https://www.gnu.org/licenses/>. |
a71ece51 | 22 | */ |
23 | ||
2c9e3090 | 24 | /* 2016-02-22: split off preset.c |
a71ece51 | 25 | * 2012-03-03: single-line Williams model string conversion |
a71ece51 | 26 | * 2011-09-03: added mrev(), mnovel() |
a71ece51 | 27 | * 2011-01-17: fixed ANSI C warnings (except preset models) |
a71ece51 | 28 | * 2010-12-26: renamed CRC RevEng |
29 | * 2010-12-18: minor change to mtostr() output format | |
a78a3d9d | 30 | * 2010-12-15: added mcmp() |
31 | * 2010-12-14: finished mtostr() | |
a71ece51 | 32 | * 2010-12-12: started models.c |
33 | */ | |
34 | ||
a71ece51 | 35 | #include <stdio.h> |
36 | #include <stdlib.h> | |
37 | #include <string.h> | |
07bc72b8 | 38 | #include <inttypes.h> |
a71ece51 | 39 | #include "reveng.h" |
40 | ||
41 | /* Private declarations */ | |
42 | ||
a71ece51 | 43 | static const poly_t pzero = PZERO; |
44 | ||
a71ece51 | 45 | /* Definitions */ |
46 | ||
47 | void | |
48 | mcpy(model_t *dest, const model_t *src) { | |
49 | /* Copies the parameters of src to dest. | |
50 | * dest must be an initialised model. | |
51 | */ | |
52 | if(!dest || !src) return; | |
53 | pcpy(&dest->spoly, src->spoly); | |
54 | pcpy(&dest->init, src->init); | |
55 | pcpy(&dest->xorout, src->xorout); | |
56 | pcpy(&dest->check, src->check); | |
57 | dest->flags = src->flags; | |
58 | /* link to the name as it is static */ | |
59 | dest->name = src->name; | |
60 | } | |
61 | ||
62 | void | |
63 | mfree(model_t *model) { | |
64 | /* Frees the parameters of model. */ | |
65 | if(!model) return; | |
66 | pfree(&model->spoly); | |
67 | pfree(&model->init); | |
68 | pfree(&model->xorout); | |
69 | pfree(&model->check); | |
70 | /* not name as it is static */ | |
71 | /* not model either, it might point to an array! */ | |
72 | } | |
73 | ||
74 | int | |
75 | mcmp(const model_t *a, const model_t *b) { | |
76 | /* Compares a and b for identical effect, i.e. disregarding | |
77 | * trailing zeroes in parameter polys. | |
a78a3d9d | 78 | * Intended for bsearch(). |
a71ece51 | 79 | */ |
80 | int result; | |
81 | if(!a || !b) return(!b - !a); | |
82 | if((result = psncmp(&a->spoly, &b->spoly))) return(result); | |
83 | if((result = psncmp(&a->init, &b->init))) return(result); | |
84 | if((a->flags & P_REFIN) && (~b->flags & P_REFIN)) return(1); | |
85 | if((~a->flags & P_REFIN) && (b->flags & P_REFIN)) return(-1); | |
86 | if((a->flags & P_REFOUT) && (~b->flags & P_REFOUT)) return(1); | |
87 | if((~a->flags & P_REFOUT) && (b->flags & P_REFOUT)) return(-1); | |
88 | return(psncmp(&a->xorout, &b->xorout)); | |
89 | } | |
90 | ||
a71ece51 | 91 | char * |
92 | mtostr(const model_t *model) { | |
93 | /* Returns a malloc()-ed string containing a Williams model | |
94 | * record representing the input model. | |
95 | * mcanon() should be called on the argument before printing. | |
96 | */ | |
97 | size_t size; | |
98 | char *polystr, *initstr, *xorotstr, *checkstr, strbuf[512], *string = NULL; | |
99 | ||
100 | if(!model) return(NULL); | |
101 | polystr = ptostr(model->spoly, P_RTJUST, 4); | |
102 | initstr = ptostr(model->init, P_RTJUST, 4); | |
103 | xorotstr = ptostr(model->xorout, P_RTJUST, 4); | |
104 | checkstr = ptostr(model->check, P_RTJUST, 4); | |
105 | ||
106 | sprintf(strbuf, "%lu", plen(model->spoly)); | |
107 | size = | |
108 | 70 | |
109 | + (model->name && *model->name ? 2 + strlen(model->name) : 6) | |
110 | + strlen(strbuf) | |
111 | + (polystr && *polystr ? strlen(polystr) : 6) | |
112 | + (initstr && *initstr ? strlen(initstr) : 6) | |
113 | + (model->flags & P_REFIN ? 4 : 5) | |
114 | + (model->flags & P_REFOUT ? 4 : 5) | |
115 | + (xorotstr && *xorotstr ? strlen(xorotstr) : 6) | |
116 | + (checkstr && *checkstr ? strlen(checkstr) : 6); | |
117 | if((string = malloc(size))) { | |
118 | sprintf(strbuf, "\"%s\"", model->name); | |
119 | sprintf(string, | |
f7c1147a | 120 | "width=%lu" |
a71ece51 | 121 | "poly=0x%s " |
122 | "init=0x%s " | |
123 | "refin=%s " | |
124 | "refout=%s " | |
125 | "xorout=0x%s " | |
126 | "check=0x%s " | |
127 | "name=%s", | |
128 | plen(model->spoly), | |
129 | polystr && *polystr ? polystr : "(none)", | |
130 | initstr && *initstr ? initstr : "(none)", | |
131 | (model->flags & P_REFIN) ? "true" : "false", | |
132 | (model->flags & P_REFOUT) ? "true" : "false", | |
133 | xorotstr && *xorotstr ? xorotstr : "(none)", | |
134 | checkstr && *checkstr ? checkstr : "(none)", | |
135 | (model->name && *model->name) ? strbuf : "(none)"); | |
136 | } | |
137 | free(polystr); | |
138 | free(initstr); | |
139 | free(xorotstr); | |
140 | free(checkstr); | |
141 | if(!string) | |
142 | uerror("cannot allocate memory for model description"); | |
143 | return(string); | |
144 | } | |
145 | ||
a71ece51 | 146 | void |
147 | mcanon(model_t *model) { | |
148 | /* canonicalise a model */ | |
149 | unsigned long dlen; | |
150 | ||
151 | if(!model) return; | |
152 | ||
153 | /* extending on the right here. This preserves the functionality | |
154 | * of a presumed working model. | |
155 | */ | |
156 | psnorm(&model->spoly); | |
157 | dlen = plen(model->spoly); | |
158 | praloc(&model->init, dlen); | |
159 | praloc(&model->xorout, dlen); | |
160 | ||
a78a3d9d | 161 | /* only calculate Check if missing. Relying on all functions |
162 | * changing parameters to call mnovel(). This is to ensure that | |
163 | * the Check value stored in the preset table is printed when | |
164 | * the model is dumped. If something goes wrong with the | |
165 | * calculator then the discrepancy with the stored Check value | |
166 | * might be noticed. Storing the Check value with each preset | |
167 | * is highly preferred. | |
168 | */ | |
a71ece51 | 169 | if(!plen(model->check)) |
170 | mcheck(model); | |
171 | } | |
172 | ||
173 | void | |
174 | mcheck(model_t *model) { | |
175 | /* calculate a check for the model */ | |
176 | poly_t checkstr, check; | |
177 | ||
178 | /* generate the check string with the correct bit order */ | |
179 | checkstr = strtop("313233343536373839", model->flags, 8); | |
180 | check = pcrc(checkstr, model->spoly, model->init, pzero, model->flags); | |
181 | if(model->flags & P_REFOUT) | |
182 | prev(&check); | |
183 | psum(&check, model->xorout, 0UL); | |
184 | model->check = check; | |
185 | pfree(&checkstr); | |
186 | } | |
187 | ||
188 | void | |
189 | mrev(model_t *model) { | |
190 | /* reverse the model to calculate reversed CRCs */ | |
191 | /* Here we invert RefIn and RefOut so that the user need only | |
192 | * reverse the order of characters in the arguments, not the | |
193 | * characters themselves. If RefOut=True, the mirror image of | |
194 | * Init seen through RefOut becomes XorOut, and as RefOut | |
195 | * becomes false, the XorOut value moved to Init stays upright. | |
196 | * If RefOut=False, Init transfers to XorOut without reflection | |
197 | * but the new Init must be reflected to present the same image, | |
198 | * as RefOut becomes true. | |
199 | */ | |
200 | poly_t temp; | |
201 | ||
202 | prcp(&model->spoly); | |
203 | if(model->flags & P_REFOUT) | |
204 | prev(&model->init); | |
205 | else | |
206 | prev(&model->xorout); | |
207 | ||
208 | /* exchange init and xorout */ | |
209 | temp = model->init; | |
210 | model->init = model->xorout; | |
211 | model->xorout = temp; | |
212 | ||
213 | /* invert refin and refout */ | |
214 | model->flags ^= P_REFIN | P_REFOUT; | |
215 | ||
216 | mnovel(model); | |
217 | } | |
218 | ||
219 | void | |
220 | mnovel(model_t *model) { | |
221 | /* remove name and check string from modified model */ | |
222 | model->name = NULL; | |
223 | pfree(&model->check); | |
224 | } |