00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <stdio.h>
00014 #include <math.h>
00015 #include <ctype.h>
00016 #include <string.h>
00017 #include <strings.h>
00018 #include "mex.h"
00019 #include "mextool.h"
00020 #include "mexargcheck.h"
00021
00022 #define ERRBUFSIZE 120
00023
00024
00025 static int mexargparse1(const mxArray *arg, const char *spec);
00026 static int mexspecmatch(const mxArray *arg, char tspec, char sspec,
00027 int *sizes, int d);
00028 static int translate_spec(char *buf, const char *spec);
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 int
00065 mexargparse(
00066 int narg,
00067 const mxArray **args,
00068 const char **names,
00069 const char **specs,
00070 const char **msgs,
00071 const char *gen_msg)
00072
00073 {
00074 char errbuf[ERRBUFSIZE];
00075 char errmsg[ERRBUFSIZE];
00076 int a;
00077 int perr;
00078
00079 for (a = 0; a < narg; a++) {
00080 if (args[a] == NULL) break;
00081 if ((perr = mexargparse1(args[a], specs[a])) != 0) {
00082
00083 if (perr > 0) {
00084 translate_spec(errbuf, specs[a]);
00085 sprintf(errmsg, "%s: Arg %d = %s, %s %s%s%s",
00086 gen_msg, a+1, names[a],
00087 msgs ? (*msgs[a] == '\0' ? "" : "(") : "",
00088 msgs ? msgs[a] : "",
00089 msgs ? (*msgs[a] == '\0' ? "" : ")") : "",
00090 errbuf);
00091 }
00092
00093 else {
00094 sprintf(errmsg,
00095 "%s: internal error: parse problem, typespec <%s> for arg %d",
00096 gen_msg,
00097 specs[a],
00098 a+1);
00099 }
00100 mexErrMsgTxt(errmsg);
00101 return 0;
00102 }
00103 }
00104 return 1;
00105 }
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 static int
00116 mexargparse1(
00117 const mxArray *arg,
00118 const char *spec)
00119 {
00120 int index;
00121 char typespec, shapespec;
00122 char *spec_size;
00123 char *spec1;
00124 int *sizes;
00125 int d, dim;
00126 int spec_matched;
00127 int match;
00128
00129 index = 0;
00130 spec_matched = 0;
00131 while ((!spec_matched) && (spec[index] != '\0')) {
00132
00133
00134 typespec = spec[index++];
00135 if (!spec[index]) return(-1);
00136 shapespec = spec[index++];
00137
00138
00139
00140 if (spec[index] == '\0') {
00141 sizes = (int *) NULL; d = 0;
00142 } else if (spec[index] == '|') {
00143 index++;
00144 sizes = (int *) NULL; d = 0;
00145 } else if (spec[index] == '(') {
00146
00147
00148 spec_size = strdup(spec+index+1);
00149
00150 while (spec[index] != '\0' && spec[index] != '|')
00151 index++;
00152 if (spec[index] == '|') index++;
00153
00154 if ((spec1 = strchr(spec_size, (int) '|')) != 0)
00155 *spec1 = '\0';
00156 else
00157 spec1 = spec_size + strlen(spec_size);
00158
00159 spec1--;
00160 if (*spec1 == ')')
00161 *spec1 = '\0';
00162 else
00163 return(-1);
00164
00165 for (spec1 = spec_size, d = 1; 1 ; d++)
00166 if ((spec1 = strchr(spec1, (int) ',')) == NULL)
00167 break;
00168 else
00169 spec1++;
00170
00171 sizes = mxCalloc(d, sizeof(int));
00172
00173 for (spec1 = spec_size, dim = 0; dim < d; dim++) {
00174 if (sscanf(spec1, "%d", &(sizes[dim])) != 1)
00175 return(-1);
00176 spec1 = strchr(spec1, (int) ',') + 1;
00177 }
00178
00179 free(spec_size);
00180
00181 } else {
00182 return(-1);
00183 }
00184
00185 match = mexspecmatch(arg, typespec, shapespec, sizes, d);
00186
00187 if (sizes) mxFree(sizes);
00188
00189 if (match < 0)
00190 return(match);
00191 else
00192 spec_matched |= match;
00193 }
00194 return(spec_matched ? 0 : 1);
00195 }
00196
00197
00198
00199
00200
00201 static int
00202 mexspecmatch(
00203 const mxArray *arg,
00204 char tspec,
00205 char sspec,
00206 int *sizes,
00207 int d)
00208
00209 {
00210 double one_elem;
00211
00212
00213 switch (toupper(tspec)) {
00214 case 'R':
00215 if (!IsFullRealArray(arg))
00216 return(0);
00217 break;
00218 case 'I':
00219 if (!IsFullRealArray(arg))
00220 return(0);
00221 else {
00222 if (!IsEmpty(arg)) {
00223 one_elem = *mxGetPr(arg);
00224 if (!isnan(one_elem))
00225 if (one_elem != ((int) one_elem))
00226 return(0);
00227 }
00228 }
00229 break;
00230 case 'B':
00231 if (!IsFullRealArray(arg))
00232 return(0);
00233 else {
00234 if (!IsEmpty(arg)) {
00235 one_elem = *mxGetPr(arg);
00236 if (!isnan(one_elem))
00237 if ((one_elem != 0) && (one_elem != 1))
00238 return(0);
00239 }
00240 }
00241 break;
00242 case 'S':
00243 if (!mxIsChar(arg))
00244 return(0);
00245 break;
00246 case 'F':
00247 if (!mxIsStruct(arg))
00248 return(0);
00249 break;
00250 case 'C':
00251 if (!mxIsCell(arg))
00252 return(0);
00253 break;
00254 case 'X':
00255 break;
00256 default:
00257 return(-1);
00258 }
00259
00260 switch (toupper(sspec)) {
00261 case 'A':
00262
00263 break;
00264 case 'M':
00265
00266 if (mxGetNumberOfDimensions(arg) > 2)
00267 return(0);
00268 break;
00269 case 'V':
00270 if (!IsLooseVector(arg))
00271 return(0);
00272 break;
00273 case 'S':
00274 if (!IsLooseScalar(arg))
00275 return(0);
00276 break;
00277 default:
00278 return(-1);
00279 }
00280
00281 if (d <= 0) {
00282
00283
00284 } else if (d == 1) {
00285
00286 if (mxGetNumberOfDimensions(arg) > 2)
00287 return(0);
00288
00289 if (!((mxGetM(arg) == 1 && mxGetN(arg) == sizes[0]) ||
00290 (mxGetN(arg) == 1 && mxGetM(arg) == sizes[0])))
00291 if (sizes[0] >= 0)
00292 return(0);
00293 } else if (d >= 2) {
00294 int D = mxGetNumberOfDimensions(arg);
00295 const mwSize *dnums = mxGetDimensions(arg);
00296 int dim;
00297 if (d != D)
00298 return(0);
00299 for (dim = 0; dim < D; dim++)
00300 if (sizes[dim] >= 0 && sizes[dim] != dnums[dim])
00301 return(0);
00302 }
00303 return(1);
00304 }
00305
00306
00307
00308
00309 static int
00310 translate_spec(
00311 char *buf,
00312 const char *spec)
00313 {
00314 int index;
00315 int index2;
00316
00317 index = 0;
00318 *buf = '\0';
00319 while (spec[index]) {
00320
00321 switch (toupper(spec[index++])) {
00322 case 'R':
00323 strcat(buf, "Real");
00324 break;
00325 case 'I':
00326 strcat(buf, "Integer");
00327 break;
00328 case 'B':
00329 strcat(buf, "Boolean");
00330 break;
00331 case 'S':
00332 strcat(buf, "Char");
00333 break;
00334 case 'F':
00335 strcat(buf, "Struct");
00336 break;
00337 case 'C':
00338 strcat(buf, "Cell");
00339 break;
00340 case 'X':
00341 strcat(buf, "Any-type");
00342 break;
00343 default:
00344 strcat(buf, "!internal error, bad type spec");
00345 break;
00346 }
00347
00348 switch (toupper(spec[index++])) {
00349 case 'A':
00350 strcat(buf, " array");
00351 break;
00352 case 'M':
00353 strcat(buf, " matrix");
00354 break;
00355 case 'V':
00356 strcat(buf, " vector");
00357 break;
00358 case 'S':
00359 strcat(buf, " scalar");
00360 break;
00361 default:
00362 strcat(buf, "!internal error, bad shape spec");
00363 break;
00364 }
00365
00366 index2 = strlen(buf);
00367 while (spec[index] != '\0' && spec[index] != '|')
00368 buf[index2++] = spec[index++];
00369 if (spec[index] == '|')
00370 buf[index2++] = spec[index++];
00371 buf[index2] = '\0';
00372 }
00373 return 1;
00374 }
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423 static const mxArray *p_testm = (const mxArray *)((char *)NULL+1);
00424 static int test_status;
00425
00426
00427
00428 int start_sizechecking()
00429 {
00430 p_testm = NULL;
00431 return 1;
00432 }
00433
00434 int sizeinit(const mxArray *pm)
00435 {
00436 if (p_testm == NULL) {
00437 p_testm = pm;
00438 test_status = 0;
00439 } else {
00440
00441 mexErrMsgTxt("internal error: size checking calls in wrong order");
00442 return 0;
00443 }
00444 return 1;
00445 }
00446
00447
00448 int sizecheck(const char *msg, int num)
00449 {
00450 return sizecheck_msg(msg, NULL, num);
00451 }
00452
00453
00454 int sizecheck_msg(const char *msg, const char **argnames, int num)
00455 {
00456 char errbuf[2*ERRBUFSIZE], sbuf[ERRBUFSIZE];
00457
00458 if (!test_status) {
00459 int dim, d = mxGetNumberOfDimensions(p_testm);
00460 const mwSize *dnums = mxGetDimensions(p_testm);
00461 for (*sbuf = '\0', dim = 0; dim < d; dim++) {
00462 sprintf(errbuf, "%d", (int) dnums[dim]);
00463 strcat(sbuf, errbuf);
00464
00465 if (dim < d-1) strcat(sbuf, "x");
00466 }
00467 sprintf(errbuf, "%s: arg %s has wrong size (is %s)",
00468 msg,
00469 argnames ? argnames[num] : "",
00470 sbuf);
00471 mexErrMsgTxt(errbuf);
00472 }
00473 p_testm = NULL;
00474 return 1;
00475 }
00476
00477
00478 static int size_null_matrix_check()
00479 {
00480 if (p_testm == NULL) {
00481 mexErrMsgTxt("internal error: size checking calls in wrong order");
00482 return 0;
00483 }
00484 return 1;
00485 }
00486
00487
00488
00489
00490
00491
00492 int sizeagree(const mxArray *pm)
00493 {
00494 int d;
00495
00496 size_null_matrix_check();
00497 d = mxGetNumberOfDimensions(pm);
00498 if (d != mxGetNumberOfDimensions(p_testm))
00499 return 0;
00500 test_status |=
00501 (memcmp((void *) mxGetDimensions(p_testm),
00502 (void *) mxGetDimensions(pm),
00503 d*sizeof(int)) == 0);
00504 return 1;
00505 }
00506
00507 int sizeagreeM(const mxArray *pm)
00508 {
00509 size_null_matrix_check();
00510
00511 test_status |= (mxGetM(p_testm) == mxGetM(pm));
00512 return 1;
00513 }
00514
00515 int sizeagreeN(const mxArray *pm)
00516 {
00517 size_null_matrix_check();
00518
00519 test_status |= (mxGetN(p_testm) == mxGetN(pm));
00520 return 1;
00521 }
00522
00523
00524 int sizeagreeMN(const mxArray *pm)
00525 {
00526 if (mxGetNumberOfDimensions(p_testm) != 2) return 0;
00527 sizeagree(pm);
00528 test_status |= ((mxGetN(p_testm) == mxGetM(pm)) &&
00529 (mxGetM(p_testm) == mxGetN(pm)));
00530 return 1;
00531 }
00532
00533
00534
00535
00536
00537
00538
00539 int sizesare(int *s, int d)
00540 {
00541 size_null_matrix_check();
00542 if (d != mxGetNumberOfDimensions(p_testm)) return 0;
00543 test_status |=
00544 (memcmp((void *) mxGetDimensions(p_testm),
00545 (void *) s,
00546 d*sizeof(int)) == 0);
00547 return 1;
00548 }
00549
00550
00551 int sizeis(int m, int n)
00552 {
00553 size_null_matrix_check();
00554 if (mxGetNumberOfDimensions(p_testm) != 2) return 0;
00555 test_status |= ((mxGetM(p_testm) == m) &&
00556 (mxGetN(p_testm) == n));
00557 return 1;
00558 }
00559
00560
00561 int sizeis3(int m, int n, int p)
00562 {
00563 int s[3];
00564
00565 size_null_matrix_check();
00566 if (mxGetNumberOfDimensions(p_testm) != 3) return 0;
00567
00568 s[0] = m; s[1] = n; s[2] = p;
00569 test_status |=
00570 (memcmp((void *) mxGetDimensions(p_testm),
00571 (void *) s,
00572 3*sizeof(int)) == 0);
00573 return 1;
00574 }
00575
00576 int sizeisM(int m)
00577 {
00578 size_null_matrix_check();
00579 test_status |= (mxGetM(p_testm) == m);
00580 return 1;
00581 }
00582
00583 int sizeisN(int n)
00584 {
00585 size_null_matrix_check();
00586 test_status |= (mxGetN(p_testm) == n);
00587 return 1;
00588 }
00589
00590
00591 int sizeisMN(int m, int n)
00592 {
00593 sizeis(m, n);
00594 sizeis(n, m);
00595 return 1;
00596 }
00597