parseur

Bonjour,

Je tente de debugger ce code.

Il compile mais la console tourne en rond.

J'ai remplacé la page html par une courte phrase: même problème.

J'ai enlevé mes ajouts:

 if (pair == 0) {//(pair != '\0') && (pair != 0)
    str = str + n;
    printf("\npair %u ", str);
    pair ++;
  } else if ( (str + 1) != ' ') {
    str = str + n + 1;
    printf("%u\n", str);
    pair = 0;
    str++;
  }

Même problème.

D'abord le programme en C qui fonctionne:

Merci de votre attention,

JPD

//from C unleashed


#include <stdio.h>
#include <string.h>


char *
sepstr(char **s, char *delim) {
	char *ret;
	size_t n;

	/* sanity check */
	if (!s || !*s || !delim)
		return NULL;

	/* we return a pointer to the current value of s */
	ret = *s;

	/* first, we find out how much of '*s' is *not* in 'delim' - we'll
	 * call that value 'n'.
	 *
	 * if (*s)[n] is a null byte, the entire string contains no instances
	 * of any character in delim; otherwise, it's the first delimiter
	 * found.
	 */
	n = strcspn(*s, delim);
	if ((*s)[n]) {
		(*s)[n] = '\0';
		/* advance s to one past the first delimiter */
		*s += (n + 1);
	} else {
		/* no more strings to return */
		*s = NULL;
	}

	/* and we return the saved pointer to the old contents of *s. */
	return ret;
}

void
tok(char *s, char *delim) {
	char *tmp;

	tmp = sepstr(&s, delim);
	while (tmp) {
		if (strspn(tmp, "0123456789,") == strlen(tmp) &&
			strchr(tmp, ',')) {
			tok(tmp, ",");
		} else {
			printf("%s\n", tmp);//token: 
		}
		tmp = sepstr(&s, delim);
	}
}

void loop(){}
int main() {
	
	/* never used a fixed size buffer like this in real code! */
	char buf[1024];
	/* to eat the newline */
	char *nl;
	FILE *flptr;

	flptr = fopen("upload.html", "rw");
   if (flptr == NULL) perror ("Error opening file");
   else
   {
	while (fgets(buf, 1024, flptr)) {
		/* I consider the != NULL superfluous, but some compilers
		 * will give a warning without it.
		 */
		if ((nl = strchr(buf, '\n')) != NULL) {
			/* no need for newline */
			*nl = '\0';
		}
		tok(buf, " ");
	}

	fclose(flptr);
   }

	return 0;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


char *sepstr(char **s, char *delim) {
  char *ret;//  = (char*)malloc(strlen(*s)+1);
  size_t n;
  //int pairbuff[2048];
  static byte pair = 0;
  static int str = 0;
 // printf("%s\n", delim);
  /* sanity check */
  if (!s || !*s || !delim)
    return NULL;

  /* we return a pointer to the current value of s */
  ret = *s;
  //printf("%s\n", ret);
  /* first, we find out how much of '*s' is *not* in 'delim' - we'll
     call that value 'n'.
     if (*s)[n] is a null byte, the entire string contains no instances
     of any character in delim; otherwise, it's the first delimiter
     found.
  ligne 26  */

  n = strcspn(*s, delim);    //??http://www.cplusplus.com/reference/cstring/strcspn/

  if ((*s)[n]) {
    (*s)[n] = '\0';
    /* advance s to one past the first delimiter */
    *s += (n + 1);
  } else {
    /* no more strings to return */
    *s = NULL;
  }
  if (pair == 0) {//(pair != '\0') && (pair != 0)
    str = str + n;
    printf("\npair %u ", str);
    pair ++;
  } else if ( (str + 1) != ' ') {
    str = str + n + 1;
    printf("%u\n", str);
    pair = 0;
    str++;
  }
  /* and we return the saved pointer to the old contents of *s. */

  return ret;
}

void tok(char *s, char *delim) {
  char *tmp;
  tmp = sepstr(&s, delim);
  while (tmp) {
    if (strspn(tmp, "%") == strlen(tmp) &&
        strchr(tmp, '%')) {
      tok(tmp, delim);
    } else {
     printf("\ntoken: %s\n", tmp);
    }
    tmp = sepstr(&s, delim);
  }
}

char* unconstchar(const char* s) {
    if (!s)
        return NULL;
    int i;
    char* res = NULL;
    res = (char*)malloc(strlen(s)+1);
    if (!res) {
        fprintf(stderr, "Memory Allocation Failed! Exiting...\n");
        exit(EXIT_FAILURE);
    }
    else {
        for (i = 0; s[i] != '\0'; i++) {
            res[i] = s[i];
        }
        res[i] = '\0';
        return res;
    }
}


void setup() {
const  char *webPage =
    "<!DOCTYPE HTML><html lang=\"fr\"><head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"
    "<meta http-equiv=\"refresh\" content=\"30\"></head>"
    "<body style=\"color:#f3d6e1;\"><div style=\"font-size:3.5rem;color:green;\"><p style=\"text-align:center;\">M&eacute;t&eacute;o</p></div>"
    "<script language=\"Javascript\" type=\"text/javascript\">if (%CTEMP%>= 25){"
    "document.write(\"<div style='color:#930000;'><p style='text-align:center;'>\");}else if (%CTEMP% < 25 && %CTEMP%>= 5){"
    "document.write(\"<div style='color:#006601;'><p style='text-align:center;'>\");}else if (%CTEMP% < 5){"
    "document.write(\"<div style='color:#930000;'><p style='text-align:center;'>\");}</script>%MYDATEWITHENOUGHSPACING%"
    "</p><p>&nbsp;</p><p style='text-align:center;font-size:14pt;'>"
    "PuissanceWifi&nbsp;=&nbsp; %WIFISTRENGHT%</p><p>&nbsp;</p><p style='text-align:center;'> %CTEMP%&deg;C</p>"
    "<p style='text-align:center;'>Humidit&eacute; du sol:&nbsp;&nbsp;"
    "%VALU%&nbsp;&#37;,&nbsp;%VALUE%&#37;&nbsp;-,&nbsp;Temp&eacute;rature du sol:&nbsp;&nbsp;%GROUND%&deg;&#67;</p>"
    "<p style='text-align:center;font-size:20pt;'>Humidit&eacute;:&nbsp;"
    "<p style='text-align:center;font-size:16pt;'>%MORE_LINES%</p></div></body></html>";

  char* p = unconstchar(webPage);
  //printf("%s\n", p);

  char* percent = (char*)char('%');
  tok(p, percent);
    free(p);
}
void loop() {}
Core 1 register dump:

PC      : 0x4000c56b  PS      : 0x00060f30  A0      : 0x800d0b50  A1      : 0x3ffb1f20  
A2      : 0x3ffb81cc  A3      : 0x00000025  A4      : 0x80087cc0  A5      : 0x3ffbc5b0  
A6      : 0x00000000  A7      : 0x00000000  A8      : 0x3ffb81cc  A9      : 0x00000025  
A10     : 0x0000003c  A11     : 0x3ffbc590  A12     : 0x8008913d  A13     : 0x3ffbc590  
A14     : 0x00000008  A15     : 0x00000001  SAR     : 0x00000000  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x00000025  LBEG    : 0x400014fd  LEND    : 0x4000150d  LCOUNT  : 0xfffffed4  

Backtrace: 0x4000c56b:0x3ffb1f20 0x400d0b4d:0x3ffb1f40 0x400d0b76:0x3ffb1f60 0x400d0c17:0x3ffb1f90 0x400e6807:0x3ffb1fb0 0x40087cbd:0x3ffb1fd0
Decoding stack result
0x400d0b4d: sepstr(char**, char*) at C:\Users\Another\Documents\Arduino\StrTok\sepstrTok/sepstrTok.ino line 26
0x400d0b76: tok(char*, char*) at C:\Users\Another\Documents\Arduino\StrTok\sepstrTok/sepstrTok.ino line 52
0x400d0c17: setup() at C:\Users\Another\Documents\Arduino\StrTok\sepstrTok/sepstrTok.ino line 112
0x400e6807: loopTask(void*) at C:\Users\Another\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\cores\esp32\main.cpp line 14
0x40087cbd: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c line 143

sur quel arduino ?

ESP32 wroom

Node32s

Il y a déjà qq chose de très suspect :

  char* percent = (char*)char('%');

En aucun cas un caractère ne saurait être casté en char *.

Autrement je pense que la substitution de variables %CTEMP% dans le code de la page pourrait être avantageusement remplacée par une gestion du type templates, au lieu de faire ça manuellement.

Voir la librairie AsyncWebServer
J'en parle ici : serveur-esp32-implementation-et-test
Voir 6.3. Utiliser une template

hbachetti:
Il y a déjà qq chose de très suspect :

  char* percent = (char*)char('%');

En aucun cas un caractère ne saurait être casté en char *.

Comment faire autrement?

JPD

Le plus simple :

void tok(char *s, const char *delim) {
char *sepstr(char **s, const char *delim) {

et :
tok(p, "%");

Mais pourquoi toute cette soupe indigeste alors que la fonction strtok() existe ?

Merci pour tes infos:

Tu remarquera que strtok est utilisée: void tok(char *s, char *delim) {

Parce que je veux placer les positions des % dans un tableau pour créer ma propre fonction parseur.

Ensuite remplacer l'espace des %(a)placeholder%(b) avec str.replace(a,b, str_x).

Parce que le code OTA que j'utilise pour un serveur vient de RNT lab: et ressemble à ceci: https://lastminuteengineers.com/esp32-ota-web-updater-arduino-ide/

et n'accepte pas qu'on mêle (processor):

server.on("/webPage", HTTP_POST, [](AsyncWebServerRequest * request) {
request->send_P(200, "text/html", webPage, processor);
});

avec ses propres fonctions styles :

server.on("/serverIndex", HTTP_GET, {
server.sendHeader("Connection", "close");
server.send(200, "text/html", serverIndex);
});

Je dois donc lire ta façon de faire avec des templates.

Ou alors, en plus simple, je découpe webPage en str1 st2 str3 etc. et je reforme la ligne avec strcat(str1, info1), etc.

Merci beaucoup pour ton attention.

JPD

Je peux faire aussi avec ça.

Merci.