Changeset 65ed9dc2 in OpenModelica


Ignore:
Timestamp:
2022-06-24T15:48:34+02:00 (22 months ago)
Author:
GitHub <noreply@…>
Branches:
maintenance/v1.20, maintenance/v1.21, maintenance/v1.22, maintenance/v1.23, master
Children:
b741403, ca0b89c7
Parents:
897feb0
git-author:
Andreas <38031952+AnHeuermann@…> (06/24/22 15:48:34)
git-committer:
GitHub <noreply@…> (06/24/22 15:48:34)
Message:

Improve error messages for info.json parsing (#9139)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • OMCompiler/SimulationRuntime/c/simulation/simulation_info_json.c

    r8d9551a r65ed9dc2  
    4141#include "../util/omc_file.h"
    4242
     43/**
     44 * @brief Skip whitespace.
     45 *
     46 * @param str           Points to some locating inside JSON.
     47 * @return const char*  Points to next non-whitespace character.
     48 */
    4349static inline const char* skipSpace(const char* str)
    4450{
     
    5662}
    5763
    58 static const char* skipValue(const char* str);
    59 
    60 static inline const char* skipObjectRest(const char* str, int first)
     64static const char* skipValue(const char* str, const char* fileName);
     65
     66/**
     67 * @brief Skip rest of JSON object.
     68 *
     69 * Move forward until next '}' is reached.
     70 *
     71 * @param str           Points to some locating inside JSON object.
     72 * @param first         1 if first location in JSON object, 0 otherwise.
     73 * @param fileName      Name of JSON to parse. Used for error messages.
     74 * @return const char*  Points to location directly after JSON obbject.
     75 */
     76static inline const char* skipObjectRest(const char* str, int first, const char* fileName)
    6177{
    6278  str=skipSpace(str);
     
    6480    if (!first) {
    6581      if (*str != ',') {
    66         fprintf(stderr, "JSON object expected ',' or '}', got: %.20s\n", str);
    67         abort();
     82        errorStreamPrint(LOG_STDOUT, 1, "Failed to parse %s", fileName);
     83        errorStreamPrint(LOG_STDOUT, 0, "JSON object expected ',' or '}', got: %.20s\n", str);
     84        messageClose(LOG_STDOUT);
     85        omc_throw_function(NULL);
    6886      }
    6987      str++;
     
    7189      first = 0;
    7290    }
    73     str = skipValue(str);
     91    str = skipValue(str, fileName);
    7492    str = skipSpace(str);
    7593    if (*str++ != ':') {
    76       fprintf(stderr, "JSON object expected ':', got: %.20s\n", str);
    77       abort();
    78     }
    79     str = skipValue(str);
     94      errorStreamPrint(LOG_STDOUT, 1, "Failed to parse %s", fileName);
     95      errorStreamPrint(LOG_STDOUT, 0, "JSON object expected ':', got: %.20s\n", str);
     96      messageClose(LOG_STDOUT);
     97      omc_throw_function(NULL);
     98    }
     99    str = skipValue(str, fileName);
    80100    str = skipSpace(str);
    81101  }
     
    83103}
    84104
    85 static const char* skipValue(const char* str)
     105/**
     106 * @brief Skip JSON value.
     107 *
     108 * @param str           Points to beginning of JSON value.
     109 * @param fileName      Name of JSON to parse. Used for error messages.
     110 * @return const char*  Points to location directly after JSON value.
     111 */
     112static const char* skipValue(const char* str, const char* fileName)
    86113{
    87114  str = skipSpace(str);
     
    89116  case '{':
    90117  {
    91     str = skipObjectRest(str+1,1);
     118    str = skipObjectRest(str+1, 1, fileName);
    92119    return str;
    93120  }
     
    98125    while (*str != ']') {
    99126      if (!first && *str++ != ',') {
    100         fprintf(stderr, "JSON array expected ',' or ']', got: %.20s\n", str);
    101         abort();
     127        errorStreamPrint(LOG_STDOUT, 1, "Failed to parse %s", fileName);
     128        errorStreamPrint(LOG_STDOUT, 0, "JSON array expected ',' or ']', got: %.20s\n", str);
     129        messageClose(LOG_STDOUT);
     130        omc_throw_function(NULL);
    102131      }
    103132      first = 0;
    104       str = skipValue(str);
     133      str = skipValue(str, fileName);
    105134      str = skipSpace(str);
    106135    }
     
    111140    do {
    112141      switch (*str) {
    113       case '\0': fprintf(stderr, "Found end of file, expected end of string"); abort();
     142      case '\0':
     143        errorStreamPrint(LOG_STDOUT, 1, "Failed to parse %s", fileName);
     144        errorStreamPrint(LOG_STDOUT, 0, "Found end of file, expected end of string");
     145        messageClose(LOG_STDOUT);
     146        omc_throw_function(NULL);
    114147      case '\\':
    115148        if (*(str+1) == '\0') {
    116           fprintf(stderr, "Found end of file, expected end of string"); abort();
     149          errorStreamPrint(LOG_STDOUT, 1, "Failed to parse %s", fileName);
     150          errorStreamPrint(LOG_STDOUT, 0, "Found end of file, expected end of string");
     151          messageClose(LOG_STDOUT);
     152          omc_throw_function(NULL);
    117153        }
    118154        str+=2;
     
    124160      }
    125161    } while (1);
    126     abort();
     162    errorStreamPrint(LOG_STDOUT, 1, "Failed to parse %s", fileName);
     163    errorStreamPrint(LOG_STDOUT, 0, "Reached state that should be impossible to reach.");
     164    messageClose(LOG_STDOUT);
     165    omc_throw_function(NULL);
    127166  case '-':
    128167  case '0':
     
    140179    om_strtod(str,&endptr);
    141180    if (str == endptr) {
    142       fprintf(stderr, "Not a number, got %.20s\n", str);
    143        abort();
     181      errorStreamPrint(LOG_STDOUT, 1, "Failed to parse %s", fileName);
     182      errorStreamPrint(LOG_STDOUT, 0, "Not a number, got %.20s\n", str);
     183      messageClose(LOG_STDOUT);
     184      omc_throw_function(NULL);
    144185    }
    145186    return endptr;
    146187  }
    147188  default:
    148     fprintf(stderr, "JSON value expected, got: %.20s\n", str);
    149     abort();
    150   }
    151 }
    152 
    153 /* Does not work for escaped strings. Returns the rest of the string to parse. */
    154 static inline const char* assertStringValue(const char *str, const char *value)
     189    errorStreamPrint(LOG_STDOUT, 1, "Failed to parse %s", fileName);
     190    errorStreamPrint(LOG_STDOUT, 0, "JSON value expected, got: %.20s\n", str);
     191    messageClose(LOG_STDOUT);
     192    omc_throw_function(NULL);
     193  }
     194}
     195
     196/**
     197 * @brief Assert str points to given string.
     198 *
     199 * Does not work for escaped strings. Returns the rest of the string to parse.
     200 *
     201 * @param str           Points to beginning of string to assert.
     202 * @param value         Expected value of string.
     203 * @param fileName      Name of JSON to parse. Used for error messages.
     204 * @return const char*  Points to location directly after string.
     205 */
     206static inline const char* assertStringValue(const char *str, const char *value, const char* fileName)
    155207{
    156208  int len = strlen(value);
    157209  str = skipSpace(str);
    158210  if ('\"' != *str || strncmp(str+1,value,len) || str[len+1] != '\"') {
    159     fprintf(stderr, "JSON string value %s expected, got: %.20s\n", value, str);
    160     abort();
     211    errorStreamPrint(LOG_STDOUT, 1, "Failed to parse %s", fileName);
     212    errorStreamPrint(LOG_STDOUT, 0, "JSON string value %s expected, got: %.20s\n", value, str);
     213    messageClose(LOG_STDOUT);
     214    omc_throw_function(NULL);
    161215  }
    162216  return str + len + 2;
    163217}
    164218
    165 static inline const char* assertChar(const char *str, char c)
     219/**
     220 * @brief Assert str points to specific character.
     221 *
     222 * @param str             Pointer to character to assert.
     223 * @param c               Character str should be equal to.
     224 * @param fileName        Name of JSON to parse. Used for error messages.
     225 * @return const char*    Point to next locatin after character.
     226 */
     227static inline const char* assertChar(const char *str, char c, const char *fileName)
    166228{
    167229  str = skipSpace(str);
    168230  if (c != *str) {
    169     fprintf(stderr, "Expected '%c', got: %.20s\n", c, str);
    170      abort();
     231    errorStreamPrint(LOG_STDOUT, 1, "Failed to parse %s", fileName);
     232    errorStreamPrint(LOG_STDOUT, 0,"Expected '%c', got: %.20s\n", c, str);
     233    messageClose(LOG_STDOUT);
     234    omc_throw_function(NULL);
    171235  }
    172236  return str + 1;
    173237}
    174238
    175 static inline const char* assertNumber(const char *str, double expected)
     239/**
     240 * @brief Assert str point to specific number.
     241 *
     242 * @param str             Pointer to number to assert.
     243 * @param expected        Expected number.
     244 * @param fileName        Name of JSON to parse. Used for error messages.
     245 * @return const char*    Point to next locatin after number.
     246 */
     247static inline const char* assertNumber(const char *str, double expected, const char *fileName)
    176248{
    177249  char *endptr = NULL;
     
    180252  d = om_strtod(str, &endptr);
    181253  if (str == endptr) {
    182     fprintf(stderr, "Expected number, got: %.20s\n", str);
    183     abort();
     254    errorStreamPrint(LOG_STDOUT, 1, "Failed to parse %s", fileName);
     255    errorStreamPrint(LOG_STDOUT, 0, "Expected number, got: %.20s\n", str);
     256    messageClose(LOG_STDOUT);
     257    omc_throw_function(NULL);
    184258  }
    185259  if (d != expected) {
    186     fprintf(stderr, "Got number %f, expected: %f\n", d, expected);
    187     abort();
     260    errorStreamPrint(LOG_STDOUT, 1, "Failed to parse %s", fileName);
     261    errorStreamPrint(LOG_STDOUT, 0, "Got number %f, expected: %f\n", d, expected);
     262    messageClose(LOG_STDOUT);
     263    omc_throw_function(NULL);
    188264  }
    189265  return endptr;
    190266}
    191267
    192 static inline const char *skipFieldIfExist(const char *str,const char *name)
     268/**
     269 * @brief Skipp JSON object if it exists.
     270 *
     271 * @param str             Pointer to object/filed to skip.
     272 * @param name            Name of object to skip.
     273 * @param fileName        Name of JSON to parse. Used for error messages.
     274 * @return const char*    Point to next locatin after object.
     275 */
     276static inline const char *skipFieldIfExist(const char *str, const char *name, const char* fileName)
    193277{
    194278  const char *s = str;
     
    207291  s += 2;
    208292  s = skipSpace(s);
    209   s = skipValue(s);
     293  s = skipValue(s, fileName);
    210294  s = skipSpace(s);
    211295  s = skipSpace(s);
     
    213297}
    214298
    215 static const char* readEquation(const char *str,EQUATION_INFO *xml,int i)
     299/**
     300 * @brief Parse single equation info from JSON.
     301 *
     302 * @param str             Points to beginning of equation object.
     303 * @param xml             Equation info to fill
     304 * @param i               Index of equation inside "equations" array.
     305 * @param fileName        Name of JSON to parse. Used for error messages.
     306 * @return const char*    Point to next locatin after character.
     307 */
     308static const char* readEquation(const char *str, EQUATION_INFO *xml, int i, const char* fileName)
    216309{
    217310  int n=0,j;
    218311  const char *str2;
    219   str=assertChar(str,'{');
    220   str=assertStringValue(str,"eqIndex");
    221   str=assertChar(str,':');
    222   str=assertNumber(str,i);
     312  str=assertChar(str,'{', fileName);
     313  str=assertStringValue(str,"eqIndex", fileName);
     314  str=assertChar(str,':', fileName);
     315  str=assertNumber(str,i,fileName);
    223316  str=skipSpace(str);
    224317  xml->id = i;
    225   str = skipFieldIfExist(str, "parent");
    226   str = skipFieldIfExist(str, "section");
     318  str = skipFieldIfExist(str, "parent", fileName);
     319  str = skipFieldIfExist(str, "section", fileName);
    227320  if ((measure_time_flag & 1) && 0==strncmp(",\"tag\":\"system\"", str, 15)) {
    228321    xml->profileBlockIndex = -1;
     
    234327    xml->profileBlockIndex = 0;
    235328  }
    236   str = skipFieldIfExist(str, "tag");
    237   str = skipFieldIfExist(str, "display");
    238   str = skipFieldIfExist(str, "unknowns");
     329  str = skipFieldIfExist(str, "tag", fileName);
     330  str = skipFieldIfExist(str, "display", fileName);
     331  str = skipFieldIfExist(str, "unknowns", fileName);
    239332  if (strncmp(",\"defines\":[", str, 12)) {
    240333    xml->numVar = 0;
    241334    xml->vars = 0;
    242     str = skipObjectRest(str,0);
     335    str = skipObjectRest(str,0, fileName);
    243336    return str;
    244337  }
     
    248341    xml->numVar = 0;
    249342    xml->vars = 0;
    250     return skipObjectRest(str-1,0);
     343    return skipObjectRest(str-1,0, fileName);
    251344  }
    252345  str2 = skipSpace(str);
    253346  while (1) {
    254     str=skipValue(str);
     347    str=skipValue(str, fileName);
    255348    n++;
    256349    str=skipSpace(str);
     
    260353    str++;
    261354  };
    262   assertChar(str, ']');
     355  assertChar(str, ']', fileName);
    263356  xml->numVar = n;
    264357  xml->vars = malloc(sizeof(const char*)*n);
     
    268361    char *tmp;
    269362    int len=0;
    270     str = assertChar(str, '\"');
     363    str = assertChar(str, '\"', fileName);
    271364    while (*str != '\"' && *str) {
    272365      len++;
    273366      str++;
    274367    }
    275     str = assertChar(str, '\"');
     368    str = assertChar(str, '\"', fileName);
    276369    tmp = malloc(len+1);
    277370    strncpy(tmp, str3+1, len);
     
    279372    xml->vars[j] = tmp;
    280373    if (j != n-1) {
    281       str = assertChar(str, ',');
    282     }
    283   }
    284   str = assertChar(skipSpace(str), ']');
    285   return skipObjectRest(str,0);
    286 }
    287 
    288 static const char* readEquations(const char *str,MODEL_DATA_XML *xml)
     374      str = assertChar(str, ',', fileName);
     375    }
     376  }
     377  str = assertChar(skipSpace(str), ']', fileName);
     378  return skipObjectRest(str,0, fileName);
     379}
     380
     381/**
     382 * @brief Parse equations from info.json.
     383 *
     384 * @param str           Point to beginning of equation array at '['.
     385 * @param xml           Model data from xml
     386 * @return const char*  Point to end of equation array dirreclty after ']'.
     387 */
     388static const char* readEquations(const char *str, MODEL_DATA_XML *xml)
    289389{
    290390  int i;
    291391  xml->nProfileBlocks = measure_time_flag & 2 ? 1 : 0;
    292   str=assertChar(str,'[');
    293   str = readEquation(str,xml->equationInfo,0);
     392  str=assertChar(str,'[', xml->fileName);
     393  str = readEquation(str, xml->equationInfo, 0, xml->fileName);
    294394  for (i=1; i<xml->nEquations; i++) {
    295     str = assertChar(str,',');
    296     str = readEquation(str,xml->equationInfo+i,i);
     395    if (*str != ',') {
     396      errorStreamPrint(LOG_STDOUT, 1, "Failed to parse %s", xml->fileName);
     397      errorStreamPrint(LOG_STDOUT, 0, "Expected %ld equations, but only found %i equations.",  xml->nEquations, i-1);
     398      messageClose(LOG_STDOUT);
     399      omc_throw_function(NULL);
     400    } else {
     401      str = str + 1;
     402    }
     403    str = readEquation(str, xml->equationInfo+i, i, xml->fileName);
    297404    /* TODO: Odd, it seems there is 1 fewer equation than expected... */
    298405    /*
     
    305412    }
    306413  }
    307   str=assertChar(str,']');
     414  str=assertChar(str,']', xml->fileName);
    308415  return str;
    309416}
    310417
    311 static const char* readFunction(const char *str,FUNCTION_INFO *xml,int i)
     418static const char* readFunction(const char *str, FUNCTION_INFO *xml, int i, const char* fileName)
    312419{
    313420  FILE_INFO info = omc_dummyFileInfo;
     
    316423  const char *str2;
    317424  str=skipSpace(str);
    318   str2=assertChar(str,'"');
    319   str=skipValue(str);
     425  str2=assertChar(str,'"', fileName);
     426  str=skipValue(str, fileName);
    320427  xml->id = i;
    321428  len = str-str2;
     
    328435}
    329436
    330 static const char* readFunctions(const char *str,MODEL_DATA_XML *xml)
     437static const char* readFunctions(const char *str, MODEL_DATA_XML *xml)
    331438{
    332439  int i;
    333440  if (xml->nFunctions == 0) {
    334     str=assertChar(str,'[');
    335     str=assertChar(str,']');
     441    str=assertChar(str,'[', xml->fileName);
     442    str=assertChar(str,']', xml->fileName);
    336443    return str;
    337444  }
    338   str=assertChar(str,'[');
     445  str=assertChar(str,'[', xml->fileName);
    339446  for (i=0; i<xml->nFunctions; i++) {
    340     str = readFunction(str,xml->functionNames+i,i);
    341     str=assertChar(str,xml->nFunctions==i+1 ? ']' : ',');
     447    str = readFunction(str, xml->functionNames+i, i, xml->fileName);
     448    str=assertChar(str,xml->nFunctions==i+1 ? ']' : ',', xml->fileName);
    342449  }
    343450  return str;
    344451}
    345452
    346 static void readInfoJson(const char *str,MODEL_DATA_XML *xml)
    347 {
    348   str=assertChar(str,'{');
    349   str=assertStringValue(str,"format");
    350   str=assertChar(str,':');
    351   str=assertStringValue(str,"Transformational debugger info");
    352   str=assertChar(str,',');
    353   str=assertStringValue(str,"version");
    354   str=assertChar(str,':');
    355   str=assertChar(str,'1');
    356   str=assertChar(str,',');
    357   str=assertStringValue(str,"info");
    358   str=assertChar(str,':');
    359   str=skipValue(str);
    360   str=assertChar(str,',');
    361   str=assertStringValue(str,"variables");
    362   str=assertChar(str,':');
    363   str=skipValue(str);
    364   str=assertChar(str,',');
    365   str=assertStringValue(str,"equations");
    366   str=assertChar(str,':');
     453static void readInfoJson(const char *str, MODEL_DATA_XML *xml)
     454{
     455  str=assertChar(str,'{', xml->fileName);
     456  str=assertStringValue(str,"format", xml->fileName);
     457  str=assertChar(str,':', xml->fileName);
     458  str=assertStringValue(str,"Transformational debugger info", xml->fileName);
     459  str=assertChar(str,',', xml->fileName);
     460  str=assertStringValue(str,"version", xml->fileName);
     461  str=assertChar(str,':', xml->fileName);
     462  str=assertChar(str,'1', xml->fileName);
     463  str=assertChar(str,',', xml->fileName);
     464  str=assertStringValue(str,"info", xml->fileName);
     465  str=assertChar(str,':', xml->fileName);
     466  str=skipValue(str, xml->fileName);
     467  str=assertChar(str,',', xml->fileName);
     468  str=assertStringValue(str,"variables", xml->fileName);
     469  str=assertChar(str,':', xml->fileName);
     470  str=skipValue(str, xml->fileName);
     471  str=assertChar(str,',', xml->fileName);
     472  str=assertStringValue(str,"equations", xml->fileName);
     473  str=assertChar(str,':', xml->fileName);
    367474  str=readEquations(str,xml);
    368   str=assertChar(str,',');
    369   str=assertStringValue(str,"functions");
    370   str=assertChar(str,':');
     475  str=assertChar(str,',', xml->fileName);
     476  str=assertStringValue(str,"functions", xml->fileName);
     477  str=assertChar(str,':', xml->fileName);
    371478  str=readFunctions(str,xml);
    372   assertChar(str,'}');
    373 }
    374 
     479  assertChar(str,'}', xml->fileName);
     480}
     481
     482/**
     483 * @brief Initialize model data xml structure by parsing info.json.
     484 *
     485 * @param xml     Model info struct to initialize.
     486 */
    375487void modelInfoInit(MODEL_DATA_XML* xml)
    376488{
Note: See TracChangeset for help on using the changeset viewer.